| @@ -0,0 +1,36 @@ | |||||
| {$STATIC BaseVec 'vec2(0.0)'} | |||||
| {$CLASS Base1} | |||||
| {$FUNC 'vec2' 'TestProc' 'vec2' 'aVec'} | |||||
| vec2 tmp = aVec; | |||||
| tmp += vec2(1.0); | |||||
| return tmp; | |||||
| {$END} | |||||
| {$END} | |||||
| {$CLASS Base2} | |||||
| {$FUNC 'vec2' 'TestProc' 'vec2' 'aVec'} | |||||
| return aVec + vec2(1.0); | |||||
| {$END} | |||||
| {$END} | |||||
| {$CLASS SimpleClass $EXTENDS Base1 Base2} | |||||
| {$UNIFORM 'sampler2D' 'uTexture0'} | |||||
| {$UNIFORM 'sampler2D' 'uTexture1'} | |||||
| {$UNIFORM 'vec4' 'uColor'} | |||||
| {$FUNC 'vec2' 'TestProc' 'vec2' 'aVec'} | |||||
| vec2 v = aVec; | |||||
| v = {$INHERITED Base1 TestProc BaseVec $INLINE}; | |||||
| v = {$INHERITED Base2 'v'}; | |||||
| return v; | |||||
| {$END} | |||||
| {$MAIN} | |||||
| vec2 texCoord = {$CALL TestProc 'gl_TexCoord[0]'}; | |||||
| gl_FragColor = | |||||
| texture2D(uTexture0, texCoord) * | |||||
| texture2D(uTexture1, texCoord) * | |||||
| uColor; | |||||
| {$END} | |||||
| {$END} | |||||
| @@ -0,0 +1,19 @@ | |||||
| {$CLASS Base1} | |||||
| {$MAIN} | |||||
| gl_FragColor.r = 1.0; | |||||
| {$END} | |||||
| {$END} | |||||
| {$CLASS Base2} | |||||
| {$MAIN} | |||||
| gl_FragColor.g = 1.0; | |||||
| {$END} | |||||
| {$END} | |||||
| {$CLASS SimpleClass $EXTENDS Base1 Base2} | |||||
| {$MAIN} | |||||
| {$INHERITED Base1}; | |||||
| {$INHERITED Base2}; | |||||
| gl_FragColor.ba = vec2(1.0); | |||||
| {$END} | |||||
| {$END} | |||||
| @@ -0,0 +1,27 @@ | |||||
| uniform sampler2D uTexture0; | |||||
| uniform sampler2D uTexture1; | |||||
| uniform vec4 uColor; | |||||
| vec2 Base2_TestProc(vec2 aVec) | |||||
| { | |||||
| return aVec + vec2(1.0); | |||||
| } | |||||
| vec2 SimpleClass_TestProc(vec2 aVec) | |||||
| { | |||||
| vec2 v = aVec; | |||||
| vec2 tmp = (vec2(0.0)); | |||||
| tmp += vec2(1.0); | |||||
| v = (tmp); | |||||
| v = Base2_TestProc(v); | |||||
| return v; | |||||
| } | |||||
| void main(void) | |||||
| { | |||||
| vec2 texCoord = SimpleClass_TestProc(gl_TexCoord[0]); | |||||
| gl_FragColor = | |||||
| texture2D(uTexture0, texCoord) * | |||||
| texture2D(uTexture1, texCoord) * | |||||
| uColor; | |||||
| } | |||||
| @@ -0,0 +1,16 @@ | |||||
| void Base2_main(void) | |||||
| { | |||||
| gl_FragColor.g = 1.0; | |||||
| } | |||||
| void Base1_main(void) | |||||
| { | |||||
| gl_FragColor.r = 1.0; | |||||
| } | |||||
| void main(void) | |||||
| { | |||||
| Base1_main(); | |||||
| Base2_main(); | |||||
| gl_FragColor.ba = vec2(1.0); | |||||
| } | |||||
| @@ -48,6 +48,8 @@ type | |||||
| TTestCase_Class = class(TShaderFileTestCase) | TTestCase_Class = class(TShaderFileTestCase) | ||||
| published | published | ||||
| procedure Simple; | procedure Simple; | ||||
| procedure InheritedFunc; | |||||
| procedure InheritedMain; | |||||
| end; | end; | ||||
| implementation | implementation | ||||
| @@ -194,6 +196,16 @@ begin | |||||
| DoTest('code_Class_Simple.shdr', 'SimpleClass', 'result_Class_Simple.shdr'); | DoTest('code_Class_Simple.shdr', 'SimpleClass', 'result_Class_Simple.shdr'); | ||||
| end; | end; | ||||
| procedure TTestCase_Class.InheritedFunc; | |||||
| begin | |||||
| DoTest('code_Class_InheritedFunc.shdr', 'SimpleClass', 'result_Class_InheritedFunc.shdr'); | |||||
| end; | |||||
| procedure TTestCase_Class.InheritedMain; | |||||
| begin | |||||
| DoTest('code_Class_InheritedMain.shdr', 'SimpleClass', 'result_Class_InheritedMain.shdr'); | |||||
| end; | |||||
| initialization | initialization | ||||
| RegisterTest(TTestCase_IfElifElseEnd); | RegisterTest(TTestCase_IfElifElseEnd); | ||||
| RegisterTest(TTestCase_FuncProcMain); | RegisterTest(TTestCase_FuncProcMain); | ||||
| @@ -1,3 +1,3 @@ | |||||
| {.$DEFINE EXPRESSION_ADD_BRACKET} // add brackets to expressions | {.$DEFINE EXPRESSION_ADD_BRACKET} // add brackets to expressions | ||||
| {$DEFINE USE_BITSPACE_UTILS} // use bitSpace Utils | {$DEFINE USE_BITSPACE_UTILS} // use bitSpace Utils | ||||
| {$DEFINE DEBUG} // enable debug output | |||||
| {.$DEFINE DEBUG} // enable debug output | |||||
| @@ -25,7 +25,7 @@ const | |||||
| TOKEN_CLASS = TOKEN_CHAR_IDENT + 'CLASS'; //{$CLASS PhongLight $EXTENDS Normal Glow} | TOKEN_CLASS = TOKEN_CHAR_IDENT + 'CLASS'; //{$CLASS PhongLight $EXTENDS Normal Glow} | ||||
| TOKEN_EXTENDS = TOKEN_CHAR_IDENT + 'EXTENDS'; | TOKEN_EXTENDS = TOKEN_CHAR_IDENT + 'EXTENDS'; | ||||
| TOKEN_INHERITED = TOKEN_CHAR_IDENT + 'INHERITED'; //{$INHERITED BaseClassMethod 'param1' 'param2'} | |||||
| TOKEN_INHERITED = TOKEN_CHAR_IDENT + 'INHERITED'; //{$INHERITED BaseClass MethodName 'param1' 'param2' $INLINE} | |||||
| TOKEN_INCLUDE = TOKEN_CHAR_IDENT + 'INCLUDE'; //{$INCLUDE 'Normal.frag'} | TOKEN_INCLUDE = TOKEN_CHAR_IDENT + 'INCLUDE'; //{$INCLUDE 'Normal.frag'} | ||||
| @@ -693,7 +693,7 @@ begin | |||||
| walker := TengKeyValuePairSearchWalker.Create(sr); | walker := TengKeyValuePairSearchWalker.Create(sr); | ||||
| try | try | ||||
| walker.Name := param.Name; | walker.Name := param.Name; | ||||
| walker.SearchFlags := [sfSearchChildrenLazy, sfSearchParents]; | |||||
| walker.SearchFlags := [sfSearchChildren, sfSearchParents]; | |||||
| walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic); | walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic); | ||||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope); | walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope); | ||||
| walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | ||||
| @@ -6,7 +6,7 @@ unit uengShaderFileHelper; | |||||
| interface | interface | ||||
| uses | uses | ||||
| uengShaderPart, uengShaderFileParser; | |||||
| uengShaderPart, uengShaderFileParser, uengShaderPartClass; | |||||
| type | type | ||||
| TInfoFlag = ( | TInfoFlag = ( | ||||
| @@ -83,6 +83,16 @@ type | |||||
| property Name: String read fName write fName; | property Name: String read fName write fName; | ||||
| end; | end; | ||||
| TengInheritedSearchWalker = class(TengSearchWalker) | |||||
| private | |||||
| fName: String; | |||||
| protected | |||||
| function Check(const aPart: TengShaderPart): Boolean; override; | |||||
| public | |||||
| property Name: String read fName write fName; | |||||
| constructor Create(const aClass: TengShaderPartClass; const aResults: TengSearchResults); | |||||
| end; | |||||
| TengProcSearchWalker = class(TengSearchWalker) | TengProcSearchWalker = class(TengSearchWalker) | ||||
| private | private | ||||
| fName: String; | fName: String; | ||||
| @@ -98,7 +108,7 @@ implementation | |||||
| uses | uses | ||||
| sysutils, | sysutils, | ||||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair, uengShaderPartProc, | uengShaderFileConstants, uengShaderFileTypes, uengShaderPartKeyValuePair, uengShaderPartProc, | ||||
| uengShaderPartIf, uengShaderPartClass; | |||||
| uengShaderPartIf; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| function IsValidIdentifier(const aIdent: String): Boolean; | function IsValidIdentifier(const aIdent: String): Boolean; | ||||
| @@ -195,14 +205,12 @@ end; | |||||
| //TengSearchWalker////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //TengSearchWalker////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengSearchWalker.Visit(const aPart, aSender: TengShaderPart; const aArgs: Pointer); | procedure TengSearchWalker.Visit(const aPart, aSender: TengShaderPart; const aArgs: Pointer); | ||||
| var | |||||
| args: TArgs; | |||||
| function VisitChild(const aItem: TengShaderPart): Boolean; | function VisitChild(const aItem: TengShaderPart): Boolean; | ||||
| var | var | ||||
| c: CengShaderPart; | c: CengShaderPart; | ||||
| begin | begin | ||||
| result := (sfSearchChildren in args.Flags) and Assigned(aItem) and (aItem <> aSender); | |||||
| result := Assigned(aItem) and (aItem <> aSender); | |||||
| if not result then | if not result then | ||||
| exit; | exit; | ||||
| for c in fChildrenDoNotLeave do | for c in fChildrenDoNotLeave do | ||||
| @@ -217,7 +225,7 @@ var | |||||
| var | var | ||||
| c: CengShaderPart; | c: CengShaderPart; | ||||
| begin | begin | ||||
| result := (sfSearchParents in args.Flags) and Assigned(aPart.Parent) and (aPart.Parent <> aSender); | |||||
| result := Assigned(aPart.Parent) and (aPart.Parent <> aSender); | |||||
| if not result then | if not result then | ||||
| exit; | exit; | ||||
| for c in fParentsDoNotLeave do | for c in fParentsDoNotLeave do | ||||
| @@ -231,6 +239,7 @@ var | |||||
| var | var | ||||
| p: TengShaderPart; | p: TengShaderPart; | ||||
| c: TengShaderPartClass; | c: TengShaderPartClass; | ||||
| args: TArgs; | |||||
| nextArgs: TArgs; | nextArgs: TArgs; | ||||
| begin | begin | ||||
| if not Assigned(aPart) then | if not Assigned(aPart) then | ||||
| @@ -240,23 +249,31 @@ begin | |||||
| else | else | ||||
| args.Flags := fSearchFlags; | args.Flags := fSearchFlags; | ||||
| // visit parent | |||||
| // calculate args for next iteration | |||||
| nextArgs := args; | nextArgs := args; | ||||
| if (sfSearchChildrenLazy in nextArgs.Flags) then | if (sfSearchChildrenLazy in nextArgs.Flags) then | ||||
| nextArgs.Flags := nextArgs.Flags + [sfSearchChildren] - [sfSearchChildrenLazy]; | nextArgs.Flags := nextArgs.Flags + [sfSearchChildren] - [sfSearchChildrenLazy]; | ||||
| if Check(aPart.Parent) then | |||||
| fResults.Add(aPart.Parent); | |||||
| if VisitParent then | |||||
| Visit(aPart.Parent, aPart, @nextArgs); | |||||
| // visit inherited | |||||
| // sfSearchParents | |||||
| if (sfSearchParents in args.Flags) then begin | |||||
| if Check(aPart.Parent) then | |||||
| fResults.Add(aPart.Parent); | |||||
| if VisitParent then | |||||
| Visit(aPart.Parent, aPart, @nextArgs); | |||||
| end; | |||||
| // sfSearchInherited | |||||
| if (sfSearchInherited in args.Flags) and (aPart is TengShaderPartClass) then begin | if (sfSearchInherited in args.Flags) and (aPart is TengShaderPartClass) then begin | ||||
| for c in (aPart as TengShaderPartClass).InheritedClasses do | |||||
| for c in (aPart as TengShaderPartClass).InheritedClasses do begin | |||||
| if Check(c) then | |||||
| fResults.Add(c); | |||||
| Visit(c, aPart, @nextArgs); | Visit(c, aPart, @nextArgs); | ||||
| end; | |||||
| end; | end; | ||||
| // visit children | |||||
| // sfSearchChildren | |||||
| if (sfSearchChildren in args.Flags) then begin | if (sfSearchChildren in args.Flags) then begin | ||||
| // sfEvaluateIf, sfIgnoreIf | |||||
| if (aPart is TengShaderPartIf) then with (aPart as TengShaderPartIf) do begin | if (aPart is TengShaderPartIf) then with (aPart as TengShaderPartIf) do begin | ||||
| if (sfEvaluateIf in args.Flags) then begin | if (sfEvaluateIf in args.Flags) then begin | ||||
| if Expression.GetValue | if Expression.GetValue | ||||
| @@ -269,6 +286,7 @@ begin | |||||
| exit; | exit; | ||||
| end; | end; | ||||
| // normal children | |||||
| for p in aPart do begin | for p in aPart do begin | ||||
| if Check(p) then | if Check(p) then | ||||
| fResults.Add(p); | fResults.Add(p); | ||||
| @@ -309,6 +327,26 @@ begin | |||||
| ((aPart as TengShaderPartKeyValuePair).Name = fName); | ((aPart as TengShaderPartKeyValuePair).Name = fName); | ||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //TengInheritedSearchWalker///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TengInheritedSearchWalker.Check(const aPart: TengShaderPart): Boolean; | |||||
| begin | |||||
| result := | |||||
| inherited Check(aPart) and | |||||
| (aPart is TengShaderPartClass) and | |||||
| ((aPart as TengShaderPartClass).Name = fName); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| constructor TengInheritedSearchWalker.Create(const aClass: TengShaderPartClass; const aResults: TengSearchResults); | |||||
| begin | |||||
| inherited Create(aResults); | |||||
| ResultTypes := CengShaderPartArr.Create(TengShaderPartClass); | |||||
| SearchFlags := [sfSearchInherited, sfIgnoreOwner]; | |||||
| Owner := aClass; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| //TengProcSearchWalker////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //TengProcSearchWalker////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -17,6 +17,7 @@ uses | |||||
| type | type | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| TengGenerateFlag = ( | TengGenerateFlag = ( | ||||
| gfGenerateProcedureMain, // generate main procedure code | |||||
| gfGenerateProcedureCode, // generate procedure code | gfGenerateProcedureCode, // generate procedure code | ||||
| gfGenerateProcedureCall, // generate procedure call | gfGenerateProcedureCall, // generate procedure call | ||||
| gfGenerateInlineCode, // generate procedure as inline code | gfGenerateInlineCode, // generate procedure as inline code | ||||
| @@ -59,7 +60,7 @@ type | |||||
| property DebugText: String read GetDebugText; | property DebugText: String read GetDebugText; | ||||
| property Indent: Integer read fIndent; | property Indent: Integer read fIndent; | ||||
| property Token: TengGeneratorToken read fToken; | property Token: TengGeneratorToken read fToken; | ||||
| constructor Create(const aToken: TengGeneratorToken; const aText: String; const aIndent: Integer = 0); | |||||
| constructor Create(const aToken: TengGeneratorToken; const aText: String; const aIndent: Integer = High(Integer)); | |||||
| end; | end; | ||||
| TCodePartList = specialize TutlSimpleList<TCodePart>; | TCodePartList = specialize TutlSimpleList<TCodePart>; | ||||
| @@ -109,19 +110,19 @@ type | |||||
| property ProcParams: TStrings read GetProcParams; | property ProcParams: TStrings read GetProcParams; | ||||
| property MaxParameterLength: Integer read fMaxParameterLength; | property MaxParameterLength: Integer read fMaxParameterLength; | ||||
| procedure PushCode; | |||||
| procedure PushFlags(const aFlags: TengGenerateFlags); | |||||
| procedure PushProcParams(const aParams: TStrings); | |||||
| function PushCode: TengShaderGeneratorArgs; | |||||
| function PushFlags(const aFlags: TengGenerateFlags): TengShaderGeneratorArgs; | |||||
| function PushProcParams(const aParams: TStrings): TengShaderGeneratorArgs; | |||||
| procedure PopCode(const aFlags: TengPopCodeFlags); | |||||
| procedure PopFlags; | |||||
| procedure PopProcParams; | |||||
| function PopCode(const aFlags: TengPopCodeFlags): TengShaderGeneratorArgs; | |||||
| function PopFlags: TengShaderGeneratorArgs; | |||||
| function PopProcParams: TengShaderGeneratorArgs; | |||||
| function AddText(const aText: String): TengShaderGeneratorArgs; | function AddText(const aText: String): TengShaderGeneratorArgs; | ||||
| function AddToken(const aToken: String): TengShaderGeneratorArgs; | function AddToken(const aToken: String): TengShaderGeneratorArgs; | ||||
| function AddCommandEnd(const aToken: String): TengShaderGeneratorArgs; | function AddCommandEnd(const aToken: String): TengShaderGeneratorArgs; | ||||
| function AddLineBreak: TengShaderGeneratorArgs; | function AddLineBreak: TengShaderGeneratorArgs; | ||||
| function BeginBlock(const aIndent: Integer = 0): TengShaderGeneratorArgs; | |||||
| function BeginBlock(const aIndent: Integer = High(Integer)): TengShaderGeneratorArgs; | |||||
| function EndBlock(const aCanAppend: Boolean = false): TengShaderGeneratorArgs; | function EndBlock(const aCanAppend: Boolean = false): TengShaderGeneratorArgs; | ||||
| function AppendToPrevLine: TengShaderGeneratorArgs; | function AppendToPrevLine: TengShaderGeneratorArgs; | ||||
| @@ -130,8 +131,8 @@ type | |||||
| procedure AddProcedure(const aProc: TengShaderPart); | procedure AddProcedure(const aProc: TengShaderPart); | ||||
| function ExtractCurrentCommand(const aCommand: TCodeStackItem): Integer; | function ExtractCurrentCommand(const aCommand: TCodeStackItem): Integer; | ||||
| procedure ReplaceIdents(const aOld, aNew: TStrings); | |||||
| procedure ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String); | |||||
| function ReplaceIdents(const aOld, aNew: TStrings): TengShaderGeneratorArgs; | |||||
| function ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String): TengShaderGeneratorArgs; | |||||
| procedure GenerateCode(const aCode: TengShaderCode); | procedure GenerateCode(const aCode: TengShaderCode); | ||||
| @@ -234,7 +235,9 @@ begin | |||||
| gtNormal: result := '[N]' + fText; | gtNormal: result := '[N]' + fText; | ||||
| gtLineBreak: result := sLineBreak; | gtLineBreak: result := sLineBreak; | ||||
| gtCommandEnd: result := '[C]' + fText; | gtCommandEnd: result := '[C]' + fText; | ||||
| gtBlockBegin: result := format('[B%d]', [fIndent]); | |||||
| gtBlockBegin: if (fIndent = High(Integer)) | |||||
| then result := '[B]' | |||||
| else result := format('[B%d]', [fIndent]); | |||||
| gtBlockEnd: result := '[E]'; | gtBlockEnd: result := '[E]'; | ||||
| gtToken: result := '[T' + fText + ']'; | gtToken: result := '[T' + fText + ']'; | ||||
| gtAppendToPrev: result := '[A]'; | gtAppendToPrev: result := '[A]'; | ||||
| @@ -276,11 +279,36 @@ var | |||||
| f: TGenFlags; | f: TGenFlags; | ||||
| cb: TCodeBlock; | cb: TCodeBlock; | ||||
| function GetCurrentIndent(const aStr: String): Integer; | |||||
| {$IFDEF DEBUG} | |||||
| procedure GenerateDebugCode; | |||||
| var | |||||
| cp: TCodePart; | |||||
| s: String; | |||||
| begin | |||||
| s := ''; | |||||
| for cp in fItems do | |||||
| s := s + cp.DebugText; | |||||
| aCode.Text := aCode.Text + s + sLineBreak + sLineBreak; | |||||
| end; | |||||
| procedure GenerateCurrentCode(const aHeader: String); | |||||
| var | |||||
| i: Integer; | |||||
| begin | |||||
| aCode.Add(aHeader); | |||||
| for i := 0 to cb.Count-1 do | |||||
| aCode.Add(Format('[%02d]%s|', [cb.Depth[i], cb[i]])); | |||||
| aCode.Add(''); | |||||
| aCode.Add(''); | |||||
| aCode.Add(''); | |||||
| end; | |||||
| {$ENDIF} | |||||
| function GetCurrentIndent(const aStr: String; const aIgnoreEmptyLines: Boolean): Integer; | |||||
| var | var | ||||
| len: Integer; | len: Integer; | ||||
| begin | begin | ||||
| if (Trim(aStr) <> '') then begin | |||||
| if (Trim(aStr) <> '') or not aIgnoreEmptyLines then begin | |||||
| result := 1; | result := 1; | ||||
| len := Length(aStr); | len := Length(aStr); | ||||
| while (result <= len) and (aStr[result] in WHITESPACES) do | while (result <= len) and (aStr[result] in WHITESPACES) do | ||||
| @@ -290,10 +318,12 @@ var | |||||
| result := High(Integer); | result := High(Integer); | ||||
| end; | end; | ||||
| function IndentStr(const aStr: String; const aIndent: Integer): String; | |||||
| function IndentStr(const aStr: String; aIndent: Integer): String; | |||||
| var | var | ||||
| i, l: Integer; | i, l: Integer; | ||||
| begin | begin | ||||
| if (aStr = '') then | |||||
| aIndent := 0; | |||||
| if (aIndent < 0) then begin | if (aIndent < 0) then begin | ||||
| i := 1; | i := 1; | ||||
| l := Length(aStr); | l := Length(aStr); | ||||
| @@ -306,26 +336,26 @@ var | |||||
| result := aStr; | result := aStr; | ||||
| end; | end; | ||||
| procedure IndentBlock(aDepth, aIndent: Integer); | |||||
| procedure IndentBlock(aDepth, aAbsIndent: Integer); | |||||
| var | var | ||||
| i, minCurIndent: Integer; | |||||
| i, indent, minCurIndent: Integer; | |||||
| begin | begin | ||||
| i := cb.Count-1; | i := cb.Count-1; | ||||
| minCurIndent := High(Integer); | minCurIndent := High(Integer); | ||||
| while (i >= 0) and (cb.Depth[i] = aDepth) do begin | while (i >= 0) and (cb.Depth[i] = aDepth) do begin | ||||
| minCurIndent := min(minCurIndent, GetCurrentIndent(cb[i])); | |||||
| minCurIndent := min(minCurIndent, GetCurrentIndent(cb[i], true)); | |||||
| dec(i); | dec(i); | ||||
| end; | end; | ||||
| inc(i); | inc(i); | ||||
| aIndent := aIndent - minCurIndent; | |||||
| indent := aAbsIndent - minCurIndent; | |||||
| while (i < cb.Count) do begin | while (i < cb.Count) do begin | ||||
| cb[i] := IndentStr(cb[i], aIndent); | |||||
| cb[i] := IndentStr(cb[i], indent); | |||||
| cb.Depth[i] := cb.Depth[i] - 1; | cb.Depth[i] := cb.Depth[i] - 1; | ||||
| inc(i); | inc(i); | ||||
| end; | end; | ||||
| end; | end; | ||||
| procedure ProgressBlock(const aIndent, aDepth: Integer); | |||||
| procedure ProgressBlock(const aCurrentBlockIndent, aDepth: Integer); | |||||
| var | var | ||||
| cp: TCodePart; | cp: TCodePart; | ||||
| tmp: Integer; | tmp: Integer; | ||||
| @@ -364,18 +394,25 @@ var | |||||
| gtBlockBegin: begin | gtBlockBegin: begin | ||||
| Include(f, gfPrevIsEmpty); | Include(f, gfPrevIsEmpty); | ||||
| tmp := GetCurrentIndent(cb.Last); | |||||
| if (tmp <> High(Integer)) | |||||
| then tmp := aIndent + tmp | |||||
| else tmp := aIndent; | |||||
| tmp := GetCurrentIndent(cb.Last, false); | |||||
| if (tmp = High(Integer)) then | |||||
| tmp := 0; | |||||
| if (Trim(cb.Last) <> '') then | if (Trim(cb.Last) <> '') then | ||||
| inc(tmp, 4); | inc(tmp, 4); | ||||
| inc(tmp, cp.Indent); | |||||
| if (cp.Indent <> High(Integer)) then | |||||
| inc(tmp, cp.Indent); | |||||
| tmp := max(tmp, aCurrentBlockIndent); | |||||
| ProgressBlock(tmp, aDepth + 1); | ProgressBlock(tmp, aDepth + 1); | ||||
| end; | end; | ||||
| gtBlockEnd: begin | gtBlockEnd: begin | ||||
| IndentBlock(aDepth, aIndent); | |||||
| {$IFDEF DEBUG} | |||||
| GenerateCurrentCode(Format('------====== DEBUG STEP BEFORE INDENT (%d) ======------', [aCurrentBlockIndent])); | |||||
| {$ENDIF} | |||||
| IndentBlock(aDepth, aCurrentBlockIndent); | |||||
| {$IFDEF DEBUG} | |||||
| GenerateCurrentCode(Format('------====== DEBUG STEP AFTER INDENT (%d) ======------', [aCurrentBlockIndent])); | |||||
| {$ENDIF} | |||||
| exit; | exit; | ||||
| end; | end; | ||||
| @@ -389,19 +426,6 @@ var | |||||
| end; | end; | ||||
| end; | end; | ||||
| {$IFDEF DEBUG} | |||||
| procedure GenerateDebugCode; | |||||
| var | |||||
| cp: TCodePart; | |||||
| s: String; | |||||
| begin | |||||
| s := ''; | |||||
| for cp in fItems do | |||||
| s := s + cp.DebugText; | |||||
| aCode.Text := aCode.Text + s + sLineBreak + sLineBreak; | |||||
| end; | |||||
| {$ENDIF} | |||||
| var | var | ||||
| s, e: Integer; | s, e: Integer; | ||||
| begin | begin | ||||
| @@ -423,7 +447,7 @@ begin | |||||
| for i := s to e do | for i := s to e do | ||||
| aCode.Add( | aCode.Add( | ||||
| {$IFDEF DEBUG} | {$IFDEF DEBUG} | ||||
| Format('[%02d]%s', [cb.Depth[i], cb[i]]) | |||||
| Format('[%02d]%s|', [cb.Depth[i], cb[i]]) | |||||
| {$ELSE} | {$ELSE} | ||||
| cb[i] | cb[i] | ||||
| {$ENDIF} | {$ENDIF} | ||||
| @@ -580,25 +604,28 @@ begin | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengShaderGeneratorArgs.PushCode; | |||||
| function TengShaderGeneratorArgs.PushCode: TengShaderGeneratorArgs; | |||||
| begin | begin | ||||
| fCode.PushLast(TCodeStackItem.Create); | fCode.PushLast(TCodeStackItem.Create); | ||||
| result := self; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengShaderGeneratorArgs.PushFlags(const aFlags: TengGenerateFlags); | |||||
| function TengShaderGeneratorArgs.PushFlags(const aFlags: TengGenerateFlags): TengShaderGeneratorArgs; | |||||
| begin | begin | ||||
| fFlagStack.PushLast(aFlags); | fFlagStack.PushLast(aFlags); | ||||
| result := self; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengShaderGeneratorArgs.PushProcParams(const aParams: TStrings); | |||||
| function TengShaderGeneratorArgs.PushProcParams(const aParams: TStrings): TengShaderGeneratorArgs; | |||||
| begin | begin | ||||
| fProcParams.PushLast(aParams); | fProcParams.PushLast(aParams); | ||||
| result := self; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengShaderGeneratorArgs.PopCode(const aFlags: TengPopCodeFlags); | |||||
| function TengShaderGeneratorArgs.PopCode(const aFlags: TengPopCodeFlags): TengShaderGeneratorArgs; | |||||
| var | var | ||||
| csi: TCodeStackItem; | csi: TCodeStackItem; | ||||
| begin | begin | ||||
| @@ -618,18 +645,21 @@ begin | |||||
| finally | finally | ||||
| FreeAndNil(csi); | FreeAndNil(csi); | ||||
| end; | end; | ||||
| result := self; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengShaderGeneratorArgs.PopFlags; | |||||
| function TengShaderGeneratorArgs.PopFlags: TengShaderGeneratorArgs; | |||||
| begin | begin | ||||
| fFlagStack.PopLast(true); | fFlagStack.PopLast(true); | ||||
| result := self; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengShaderGeneratorArgs.PopProcParams; | |||||
| function TengShaderGeneratorArgs.PopProcParams: TengShaderGeneratorArgs; | |||||
| begin | begin | ||||
| fProcParams.PopLast; | fProcParams.PopLast; | ||||
| result := self; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -747,7 +777,7 @@ begin | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengShaderGeneratorArgs.ReplaceIdents(const aOld, aNew: TStrings); | |||||
| function TengShaderGeneratorArgs.ReplaceIdents(const aOld, aNew: TStrings): TengShaderGeneratorArgs; | |||||
| var | var | ||||
| rx: TRegExpr; | rx: TRegExpr; | ||||
| i: Integer; | i: Integer; | ||||
| @@ -765,10 +795,11 @@ begin | |||||
| finally | finally | ||||
| FreeAndNil(rx); | FreeAndNil(rx); | ||||
| end; | end; | ||||
| result := self; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| procedure TengShaderGeneratorArgs.ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String); | |||||
| function TengShaderGeneratorArgs.ReplaceReturns(const aCommand: TCodeStackItem; const aRetType, aName: String): TengShaderGeneratorArgs; | |||||
| var | var | ||||
| rx: TRegExpr; | rx: TRegExpr; | ||||
| RetCount, i, j: Integer; | RetCount, i, j: Integer; | ||||
| @@ -778,7 +809,7 @@ var | |||||
| begin | begin | ||||
| rx := TRegExpr.Create; | rx := TRegExpr.Create; | ||||
| try | try | ||||
| rx.Expression := '([^A-z0-9_]+|^)return([^A-z0-9_]+|$)'; | |||||
| rx.Expression := '^(.*?\s+)return\s*(.*)$'; | |||||
| csi := fCode.Last; | csi := fCode.Last; | ||||
| // find number of "return" in code | // find number of "return" in code | ||||
| @@ -812,7 +843,7 @@ begin | |||||
| // replace "return" with temp variable | // replace "return" with temp variable | ||||
| for cp in csi.Items do | for cp in csi.Items do | ||||
| cp.Text := rx.Replace(cp.Text, '$1' + s + ' =$2', true); | |||||
| cp.Text := rx.Replace(cp.Text, '$1' + s + ' = $2', true); | |||||
| // merge code | // merge code | ||||
| csi.Merge(aCommand, csi.Items.Count); | csi.Merge(aCommand, csi.Items.Count); | ||||
| @@ -825,16 +856,20 @@ begin | |||||
| cp := csi.Items[i]; | cp := csi.Items[i]; | ||||
| if rx.Exec(cp.Text) then begin | if rx.Exec(cp.Text) then begin | ||||
| csi.Items.Insert(i, TCodePart.Create(gtNormal, rx.Match[1])); | csi.Items.Insert(i, TCodePart.Create(gtNormal, rx.Match[1])); | ||||
| cp.Text := rx.Replace(cp.Text, '(', true); | |||||
| cp.Text := rx.Replace(cp.Text, '($2', true); | |||||
| // replace last gtCommandEnd with ')' and delete everything behind | |||||
| // replace last gtCommandEnd with ')' and delete everything code behind | |||||
| j := csi.Items.Count-1; | j := csi.Items.Count-1; | ||||
| while (j > i) and not (csi.Items[j].Token = gtCommandEnd) do | while (j > i) and not (csi.Items[j].Token = gtCommandEnd) do | ||||
| dec(j); | dec(j); | ||||
| if (j > i) then | if (j > i) then | ||||
| csi.Items[j] := TCodePart.Create(gtNormal, ')'); | csi.Items[j] := TCodePart.Create(gtNormal, ')'); | ||||
| while (csi.Items.Count-1 > j) do | |||||
| csi.Items.PopLast(true); | |||||
| inc(j); | |||||
| while (j < csi.Items.Count) do begin | |||||
| if (csi.Items[j].Token in [gtNormal, gtLineBreak, gtCommandEnd]) | |||||
| then csi.Items.Delete(j) | |||||
| else inc(j); | |||||
| end; | |||||
| // merge | // merge | ||||
| csi.Merge(aCommand, i+1); | csi.Merge(aCommand, i+1); | ||||
| @@ -845,6 +880,7 @@ begin | |||||
| finally | finally | ||||
| FreeAndNil(rx); | FreeAndNil(rx); | ||||
| end; | end; | ||||
| result := self; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -7,7 +7,8 @@ interface | |||||
| uses | uses | ||||
| Classes, SysUtils, | Classes, SysUtils, | ||||
| uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs; | |||||
| uengShaderPart, uengShaderCodePart, uengShaderFileParser, uengShaderGeneratorArgs, uengShaderPartClass, | |||||
| uengShaderPartProc, uengShaderPartKeyValuePair; | |||||
| type | type | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -16,6 +17,8 @@ type | |||||
| private { member } | private { member } | ||||
| fName: String; | fName: String; | ||||
| fParameters: TStringList; | fParameters: TStringList; | ||||
| function FindKeyValuePair(const aName: String): TengShaderPartKeyValuePair; | |||||
| protected { virtual getter } | protected { virtual getter } | ||||
| function GetText: String; override; | function GetText: String; override; | ||||
| function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | ||||
| @@ -28,7 +31,6 @@ type | |||||
| private | private | ||||
| function GetParameters: TStrings; | function GetParameters: TStrings; | ||||
| public | public | ||||
| property Name: String read fName; | |||||
| property Parameters: TStrings read GetParameters; | property Parameters: TStrings read GetParameters; | ||||
| constructor Create(const aParent: TengShaderPart); override; | constructor Create(const aParent: TengShaderPart); override; | ||||
| @@ -41,8 +43,12 @@ type | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| TengShaderPartInherited = class(TengShaderPartCall) | TengShaderPartInherited = class(TengShaderPartCall) | ||||
| { Class Methods } | |||||
| { Code Loading & Storage } | |||||
| private | |||||
| fInline: Boolean; | |||||
| fClass: TengShaderPartClass; | |||||
| protected | protected | ||||
| function GetText: String; override; | |||||
| function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | function ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; override; | ||||
| { Code Generation } | { Code Generation } | ||||
| @@ -58,23 +64,44 @@ type | |||||
| implementation | implementation | ||||
| uses | uses | ||||
| uengShaderPartProc, uengShaderPartClass, uengShaderFileConstants, uengShaderFileTypes, | |||||
| uengShaderFileHelper, uengShaderGenerator, uengShaderFile; | |||||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderGenerator, | |||||
| uengShaderFile, uengShaderPartScope; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| //TengShaderPartCall//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //TengShaderPartCall//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TengShaderPartCall.FindKeyValuePair(const aName: String): TengShaderPartKeyValuePair; | |||||
| var | |||||
| sr: TengSearchResults; | |||||
| walker: TengKeyValuePairSearchWalker; | |||||
| begin | |||||
| sr := TengSearchResults.Create; | |||||
| walker := TengKeyValuePairSearchWalker.Create(sr); | |||||
| try | |||||
| walker.Name := aName; | |||||
| walker.SearchFlags := [sfSearchChildren, sfSearchParents]; | |||||
| walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartProperty, TengShaderPartStatic); | |||||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartScope); | |||||
| walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | |||||
| walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); | |||||
| walker.Run(fParent); | |||||
| result := (ExtractSearchResult(self, aName, sr) as TengShaderPartKeyValuePair); | |||||
| finally | |||||
| FreeAndNil(walker); | |||||
| FreeAndNil(sr); | |||||
| end; | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| function TengShaderPartCall.GetText: String; | function TengShaderPartCall.GetText: String; | ||||
| var | var | ||||
| i: Integer; | i: Integer; | ||||
| begin | begin | ||||
| result := TOKEN_CHAR_BEGIN + GetTokenName; | |||||
| if (fName <> '') then | |||||
| result := result + ' ' + fName; | |||||
| result := TOKEN_CHAR_BEGIN + GetTokenName + ' ' + fName; | |||||
| for i := 0 to fParameters.Count-1 do begin | for i := 0 to fParameters.Count-1 do begin | ||||
| if (PtrInt(fParameters.Objects[i]) <> 0) | |||||
| then result := result + ' ' + TOKEN_CHAR_QUOTE + fParameters[i] + TOKEN_CHAR_QUOTE | |||||
| else result := result + ' ' + fParameters[i]; | |||||
| if Assigned(fParameters.Objects[i]) | |||||
| then result := result + ' ' + TengShaderPartKeyValuePair(fParameters.Objects[i]).Name | |||||
| else result := result + ' ' + TOKEN_CHAR_QUOTE + fParameters[i] + TOKEN_CHAR_QUOTE; | |||||
| end; | end; | ||||
| result := result + TOKEN_CHAR_END; | result := result + TOKEN_CHAR_END; | ||||
| end; | end; | ||||
| @@ -89,15 +116,18 @@ begin | |||||
| if (aParams.Count < 2) then | if (aParams.Count < 2) then | ||||
| raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self); | raise EengInvalidParamterCount.Create(GetTokenName, 2, -1, self); | ||||
| result := ''; | |||||
| fParameters.Clear; | fParameters.Clear; | ||||
| with aParams[1] do begin | |||||
| if not IsValidIdentifier(fName) then | |||||
| raise EengInvalidIdentifier.Create(Name, self); | |||||
| fName := Name; | |||||
| result := ''; | |||||
| fName := aParams[1].Name; | |||||
| if not IsValidIdentifier(fName) then | |||||
| raise EengInvalidIdentifier.Create(fName, aParams[1].Line, aParams[1].Col, Filename, self); | |||||
| for i := 2 to aParams.Count-1 do begin | |||||
| if not aParams[i].Quoted | |||||
| then fParameters.AddObject(aParams[i].Name, FindKeyValuePair(aParams[i].Name)) | |||||
| else fParameters.AddObject(aParams[i].Name, nil); | |||||
| end; | end; | ||||
| for i := 2 to aParams.Count-1 do | |||||
| fParameters.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted))); | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -111,7 +141,7 @@ begin | |||||
| sr := TengSearchResults.Create; | sr := TengSearchResults.Create; | ||||
| walker := TengProcSearchWalker.Create(sr); | walker := TengProcSearchWalker.Create(sr); | ||||
| try | try | ||||
| walker.Name := Name; | |||||
| walker.Name := fName; | |||||
| walker.SearchFlags := [sfEvaluateIf, sfSearchChildren, sfSearchInherited]; | walker.SearchFlags := [sfEvaluateIf, sfSearchChildren, sfSearchInherited]; | ||||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator); | walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderGenerator); | ||||
| walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | walker.ChildrenForceLeave := CengShaderPartArr.Create(TengShaderFile); | ||||
| @@ -160,25 +190,92 @@ end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| //TengShaderPartInherited/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //TengShaderPartInherited/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | |||||
| function TengShaderPartInherited.GetText: String; | |||||
| begin | |||||
| result := inherited GetText; | |||||
| if fInline then | |||||
| Insert(' ' + TOKEN_INLINE, result, Length(result) - 1); | |||||
| end; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| function TengShaderPartInherited.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | function TengShaderPartInherited.ParseIntern(const aArgs: TengParseArgs; const aParams: TengTokenParameterList): String; | ||||
| function FindInheritedClass(const aName: string): TengShaderPartClass; | |||||
| var | |||||
| sr: TengSearchResults; | |||||
| walker: TengInheritedSearchWalker; | |||||
| begin | |||||
| sr := TengSearchResults.Create; | |||||
| walker := TengInheritedSearchWalker.Create((GetParent(TengShaderPartClass) as TengShaderPartClass), sr); | |||||
| try | |||||
| walker.Name := aName; | |||||
| walker.Run(walker.Owner); | |||||
| result := (ExtractSearchResult(self, aName, sr, [ifWarning]) as TengShaderPartClass); | |||||
| finally | |||||
| FreeAndNil(walker); | |||||
| FreeAndNil(sr); | |||||
| end; | |||||
| end; | |||||
| type | |||||
| TExpectedPart = (epClass, epProc, epParam); | |||||
| TExpectedParts = set of TExpectedPart; | |||||
| var | var | ||||
| i: Integer; | i: Integer; | ||||
| expected: TExpectedParts; | |||||
| begin | begin | ||||
| if (aParams[0].Name <> GetTokenName) then with aParams[0] do | if (aParams[0].Name <> GetTokenName) then with aParams[0] do | ||||
| raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self); | raise EengInvalidToken.Create(ClassName, Name, Line, Col, Filename, self); | ||||
| fName := ''; | |||||
| fName := ''; | |||||
| result := ''; | |||||
| fClass := nil; | |||||
| fInline := false; | |||||
| expected := [epClass, epProc, epParam]; | |||||
| fParameters.Clear; | fParameters.Clear; | ||||
| if (aParams.Count >= 2) then begin | |||||
| if not IsValidIdentifier(aParams[1].Name) and (aParams[1].Name <> TOKEN_MAIN) then | |||||
| with aParams[1] do | |||||
| raise EengInvalidIdentifier.Create(Name, Line, Col, Filename, self); | |||||
| fName := aParams[1].Name; | |||||
| for i := 2 to aParams.Count-1 do | |||||
| fParameters.AddObject(aParams[i].Name, TObject(PtrInt(aParams[i].Quoted))); | |||||
| for i := 1 to aParams.Count-1 do begin | |||||
| // quoted parameter | |||||
| if aParams[i].Quoted then begin | |||||
| if not (epParam in expected) then | |||||
| raise EengUnexpectedToken.Create(aParams[i].Name, '[none]', aParams[i].Line, aParams[i].Col, Filename, self); | |||||
| fParameters.AddObject(aParams[i].Name, nil); | |||||
| expected := expected - [epClass, epProc]; | |||||
| continue; | |||||
| end; | |||||
| // inline | |||||
| if (aParams[i].Name = TOKEN_INLINE) then begin | |||||
| fInline := true; | |||||
| continue; | |||||
| end; | |||||
| // class | |||||
| if (epClass in expected) then begin | |||||
| fClass := FindInheritedClass(aParams[i].Name); | |||||
| if Assigned(fClass) then begin | |||||
| expected := expected - [epClass]; | |||||
| continue; | |||||
| end; | |||||
| end; | |||||
| // proc | |||||
| if (epProc in expected) then begin | |||||
| fName := aParams[i].Name; | |||||
| expected := expected - [epClass, epProc]; | |||||
| continue; | |||||
| end; | |||||
| // unquoted param | |||||
| if (epParam in expected) then begin | |||||
| fParameters.AddObject(aParams[i].Name, FindKeyValuePair(aParams[i].Name)); | |||||
| continue; | |||||
| end; | |||||
| raise EengUnexpectedToken.Create(aParams[i].Name, '[none]', aParams[i].Line, aParams[i].Col, Filename, self); | |||||
| end; | end; | ||||
| result := ''; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -188,20 +285,22 @@ procedure TengShaderPartInherited.GenerateCodeIntern(const aArgs: TengShaderGene | |||||
| var | var | ||||
| sr: TengSearchResults; | sr: TengSearchResults; | ||||
| walker: TengProcSearchWalker; | walker: TengProcSearchWalker; | ||||
| ParentProc: TengShaderPartProc; | |||||
| c: TengShaderPartClass; | |||||
| begin | begin | ||||
| sr := TengSearchResults.Create; | sr := TengSearchResults.Create; | ||||
| walker := TengProcSearchWalker.Create(sr); | walker := TengProcSearchWalker.Create(sr); | ||||
| try | try | ||||
| ParentProc := (GetParent(TengShaderPartProc) as TengShaderPartProc); | |||||
| walker.Name := Name; | |||||
| walker.Name := fName; | |||||
| if (walker.Name = '') then | if (walker.Name = '') then | ||||
| walker.Name := ParentProc.Name; | |||||
| walker.Owner := ParentProc; | |||||
| walker.SearchFlags := [sfEvaluateIf, sfIgnoreOwner, sfSearchChildrenLazy, sfSearchInherited]; | |||||
| walker.Name := (GetParent(TengShaderPartProc) as TengShaderPartProc).Name; | |||||
| walker.SearchFlags := [sfEvaluateIf, sfSearchChildren, sfSearchInherited]; | |||||
| walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); | walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); | ||||
| walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); | walker.ChildrenDoNotLeave := CengShaderPartArr.Create(TengShaderPartClass); | ||||
| walker.Run(ParentProc); | |||||
| if not Assigned(fClass) then begin | |||||
| for c in (GetParent(TengShaderPartClass) as TengShaderPartClass).InheritedClasses do | |||||
| walker.Run(c); | |||||
| end else | |||||
| walker.Run(fClass); | |||||
| result := (ExtractSearchResult(self, walker.Name, sr) as TengShaderPartProc); | result := (ExtractSearchResult(self, walker.Name, sr) as TengShaderPartProc); | ||||
| finally | finally | ||||
| FreeAndNil(walker); | FreeAndNil(walker); | ||||
| @@ -211,7 +310,9 @@ procedure TengShaderPartInherited.GenerateCodeIntern(const aArgs: TengShaderGene | |||||
| procedure GenCode(const aProc: TengShaderPartProc; const aParams: TStrings); | procedure GenCode(const aProc: TengShaderPartProc; const aParams: TStrings); | ||||
| begin | begin | ||||
| aArgs.PushFlags(aArgs.Flags + [gfGenerateInlineCode]); | |||||
| if fInline | |||||
| then aArgs.PushFlags(aArgs.Flags + [gfGenerateInlineCode, gfGenerateProcedureCall] - [gfGenerateProcedureCode]) | |||||
| else aArgs.PushFlags(aArgs.Flags + [gfGenerateProcedureCall] - [gfGenerateProcedureCode]); | |||||
| aArgs.PushProcParams(aParams); | aArgs.PushProcParams(aParams); | ||||
| try | try | ||||
| aProc.GenerateCodeIntern(aArgs); | aProc.GenerateCodeIntern(aArgs); | ||||
| @@ -231,6 +332,9 @@ begin | |||||
| if (fParameters.Count > 0) then begin | if (fParameters.Count > 0) then begin | ||||
| if (fParameters.Count <> proc.ParameterCount) then | if (fParameters.Count <> proc.ParameterCount) then | ||||
| raise EengInvalidParamterCount.Create(proc.name + ' expexts ' + IntToStr(proc.ParameterCount) + ' parameters', self); | raise EengInvalidParamterCount.Create(proc.name + ' expexts ' + IntToStr(proc.ParameterCount) + ' parameters', self); | ||||
| for i := 0 to fParameters.Count-1 do | |||||
| if Assigned(fParameters.Objects[i]) then | |||||
| fParameters[i] := TengShaderPartKeyValuePair(fParameters.Objects[i]).Value; | |||||
| GenCode(proc, fParameters); | GenCode(proc, fParameters); | ||||
| end else begin | end else begin | ||||
| params := TStringList.Create; | params := TStringList.Create; | ||||
| @@ -207,7 +207,7 @@ begin | |||||
| walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain); | walker.ResultTypes := CengShaderPartArr.Create(TengShaderPartMain); | ||||
| walker.Run(self); | walker.Run(self); | ||||
| main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr) as TengShaderPartMain); | main := (ExtractSearchResult(self, TengShaderPartMain.GetTokenName, sr) as TengShaderPartMain); | ||||
| aArgs.PushFlags([gfGenerateProcedureCode]); | |||||
| aArgs.PushFlags([gfGenerateProcedureCode, gfGenerateProcedureMain]); | |||||
| try | try | ||||
| main.GenerateCodeIntern(aArgs); | main.GenerateCodeIntern(aArgs); | ||||
| finally | finally | ||||
| @@ -68,7 +68,6 @@ begin | |||||
| walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); | walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); | ||||
| walker.SearchFlags := [ | walker.SearchFlags := [ | ||||
| sfSearchChildrenLazy, | sfSearchChildrenLazy, | ||||
| sfSearchChildren, | |||||
| sfSearchParents | sfSearchParents | ||||
| ]; | ]; | ||||
| walker.Run(self); | walker.Run(self); | ||||
| @@ -147,7 +147,6 @@ begin | |||||
| walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); | walker.ParentsDoNotLeave := CengShaderPartArr.Create(TengShaderFile); | ||||
| walker.SearchFlags := [ | walker.SearchFlags := [ | ||||
| sfSearchChildrenLazy, | sfSearchChildrenLazy, | ||||
| sfSearchChildren, | |||||
| sfSearchParents | sfSearchParents | ||||
| ]; | ]; | ||||
| walker.Run(self); | walker.Run(self); | ||||
| @@ -39,7 +39,7 @@ type | |||||
| { Code Generation } | { Code Generation } | ||||
| protected | protected | ||||
| function GenerateHeaderCode: String; virtual; | |||||
| function GenerateHeaderCode(const aArgs: TengShaderGeneratorArgs): String; virtual; | |||||
| procedure GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); virtual; | procedure GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); virtual; | ||||
| public | public | ||||
| procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; | procedure GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); override; | ||||
| @@ -68,7 +68,7 @@ type | |||||
| { Code Generation } | { Code Generation } | ||||
| protected | protected | ||||
| function GenerateHeaderCode: String; override; | |||||
| function GenerateHeaderCode(const aArgs: TengShaderGeneratorArgs): String; override; | |||||
| { General } | { General } | ||||
| public | public | ||||
| @@ -86,7 +86,7 @@ type | |||||
| { Code Generation } | { Code Generation } | ||||
| protected | protected | ||||
| function GenerateHeaderCode: String; override; | |||||
| function GenerateHeaderCode(const aArgs: TengShaderGeneratorArgs): String; override; | |||||
| procedure GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); override; | procedure GenerateInlineCode(const aArgs: TengShaderGeneratorArgs); override; | ||||
| { Class Methods } | { Class Methods } | ||||
| @@ -98,7 +98,7 @@ implementation | |||||
| uses | uses | ||||
| RegExpr, | RegExpr, | ||||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper; | |||||
| uengShaderFileConstants, uengShaderFileTypes, uengShaderFileHelper, uengShaderPartClass; | |||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| //TengShaderPartProc//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //TengShaderPartProc//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -184,9 +184,10 @@ begin | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| function TengShaderPartProc.GenerateHeaderCode: String; | |||||
| function TengShaderPartProc.GenerateHeaderCode(const aArgs: TengShaderGeneratorArgs): String; | |||||
| var | var | ||||
| p: TengShaderPartProcParam; | p: TengShaderPartProcParam; | ||||
| c: TengShaderPartClass; | |||||
| begin | begin | ||||
| result := ''; | result := ''; | ||||
| for p in fParameters do begin | for p in fParameters do begin | ||||
| @@ -196,7 +197,9 @@ begin | |||||
| end; | end; | ||||
| if (result = '') then | if (result = '') then | ||||
| result := 'void'; | result := 'void'; | ||||
| result := 'void ' + fName + '(' + result + ')'; | |||||
| if GetParent(TengShaderPartClass, c) | |||||
| then result := 'void ' + c.Name + '_' + fName + '(' + result + ')' | |||||
| else result := 'void ' + fName + '(' + result + ')'; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -240,6 +243,7 @@ end; | |||||
| procedure TengShaderPartProc.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | procedure TengShaderPartProc.GenerateCodeIntern(const aArgs: TengShaderGeneratorArgs); | ||||
| var | var | ||||
| s, params: String; | s, params: String; | ||||
| c: TengShaderPartClass; | |||||
| begin | begin | ||||
| // generate inline code | // generate inline code | ||||
| if (aArgs.Flags * [gfGenerateProcedureCall, gfGenerateProcedureCode] <> []) and | if (aArgs.Flags * [gfGenerateProcedureCall, gfGenerateProcedureCode] <> []) and | ||||
| @@ -252,7 +256,7 @@ begin | |||||
| end else if (gfGenerateProcedureCode in aArgs.Flags) then begin | end else if (gfGenerateProcedureCode in aArgs.Flags) then begin | ||||
| aArgs | aArgs | ||||
| .AddLineBreak | .AddLineBreak | ||||
| .AddText(GenerateHeaderCode) | |||||
| .AddText(GenerateHeaderCode(aArgs)) | |||||
| .AddLineBreak | .AddLineBreak | ||||
| .AddCommandEnd('{') | .AddCommandEnd('{') | ||||
| .AddLineBreak | .AddLineBreak | ||||
| @@ -274,7 +278,9 @@ begin | |||||
| params := params + ', '; | params := params + ', '; | ||||
| params := params + s; | params := params + s; | ||||
| end; | end; | ||||
| aArgs.AddText(fName + '(' + params + ')'); | |||||
| if GetParent(TengShaderPartClass, c) | |||||
| then aArgs.AddText(c.Name + '_' + fName + '(' + params + ')') | |||||
| else aArgs.AddText(fName + '(' + params + ')'); | |||||
| aArgs.AddProcedure(self); | aArgs.AddProcedure(self); | ||||
| end; | end; | ||||
| end; | end; | ||||
| @@ -327,9 +333,13 @@ begin | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| function TengShaderPartMain.GenerateHeaderCode: String; | |||||
| function TengShaderPartMain.GenerateHeaderCode(const aArgs: TengShaderGeneratorArgs): String; | |||||
| var | |||||
| c: TengShaderPartClass; | |||||
| begin | begin | ||||
| result := 'void main(void)'; | |||||
| if not (gfGenerateProcedureMain in aArgs.Flags) and GetParent(TengShaderPartClass, c) | |||||
| then result := 'void ' + c.Name + '_main(void)' | |||||
| else result := 'void main(void)'; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -368,9 +378,10 @@ begin | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| function TengShaderPartFunc.GenerateHeaderCode: String; | |||||
| function TengShaderPartFunc.GenerateHeaderCode(const aArgs: TengShaderGeneratorArgs): String; | |||||
| var | var | ||||
| p: TengShaderPartProcParam; | p: TengShaderPartProcParam; | ||||
| c: TengShaderPartClass; | |||||
| begin | begin | ||||
| result := ''; | result := ''; | ||||
| for p in fParameters do begin | for p in fParameters do begin | ||||
| @@ -380,7 +391,9 @@ begin | |||||
| end; | end; | ||||
| if (result = '') then | if (result = '') then | ||||
| result := 'void'; | result := 'void'; | ||||
| result := fReturnType + ' ' + fName + '(' + result + ')'; | |||||
| if GetParent(TengShaderPartClass, c) | |||||
| then result := fReturnType + ' ' + c.Name + '_' + fName + '(' + result + ')' | |||||
| else result := fReturnType + ' ' + fName + '(' + result + ')'; | |||||
| end; | end; | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -392,15 +405,17 @@ begin | |||||
| csi := TengShaderGeneratorArgs.TCodeStackItem.Create; | csi := TengShaderGeneratorArgs.TCodeStackItem.Create; | ||||
| try | try | ||||
| indent := aArgs.ExtractCurrentCommand(csi); | indent := aArgs.ExtractCurrentCommand(csi); | ||||
| aArgs.PushCode; | |||||
| aArgs.BeginBlock; | |||||
| aArgs | |||||
| .PushCode | |||||
| .BeginBlock; | |||||
| try | try | ||||
| inherited GenerateInlineCode(aArgs); | inherited GenerateInlineCode(aArgs); | ||||
| finally | finally | ||||
| aArgs.EndBlock; | |||||
| aArgs.AddText(StringOfChar(' ', indent)); | |||||
| aArgs.ReplaceReturns(csi, fReturnType, fName); | |||||
| aArgs.PopCode([pcfAppend]); | |||||
| aArgs | |||||
| .EndBlock | |||||
| .AddText(StringOfChar(' ', indent)) | |||||
| .ReplaceReturns(csi, fReturnType, fName) | |||||
| .PopCode([pcfAppend]); | |||||
| end; | end; | ||||
| finally | finally | ||||
| FreeAndNil(csi); | FreeAndNil(csi); | ||||