|
|
@@ -148,6 +148,69 @@ uses |
|
|
|
const |
|
|
|
WHITESPACES = [' ', #9]; |
|
|
|
|
|
|
|
type |
|
|
|
TCodeBlock = class(TStringList) |
|
|
|
private |
|
|
|
function GetLast: String; |
|
|
|
function GetDepth(const aIndex: Integer): Integer; |
|
|
|
procedure SetLast(aValue: String); |
|
|
|
procedure SetDepth(const aIndex: Integer; aValue: Integer); |
|
|
|
public |
|
|
|
property Last: String read GetLast write SetLast; |
|
|
|
property Depth[const aIndex: Integer]: Integer read GetDepth write SetDepth; |
|
|
|
|
|
|
|
function Add(const aString: String; const aDepth: Integer): Integer; reintroduce; |
|
|
|
procedure Clear; override; |
|
|
|
|
|
|
|
constructor Create; |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
//TCodeBlock//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
function TCodeBlock.GetLast: String; |
|
|
|
begin |
|
|
|
result := Get(Count-1); |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
function TCodeBlock.GetDepth(const aIndex: Integer): Integer; |
|
|
|
begin |
|
|
|
result := PtrInt(Objects[aIndex]); |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
procedure TCodeBlock.SetLast(aValue: String); |
|
|
|
begin |
|
|
|
Put(Count-1, aValue); |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
procedure TCodeBlock.SetDepth(const aIndex: Integer; aValue: Integer); |
|
|
|
begin |
|
|
|
Objects[aIndex] := TObject(PtrInt(aValue)); |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
function TCodeBlock.Add(const aString: String; const aDepth: Integer): Integer; |
|
|
|
begin |
|
|
|
result := inherited AddObject(aString, TObject(PtrInt(aDepth))); |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
procedure TCodeBlock.Clear; |
|
|
|
begin |
|
|
|
inherited Clear; |
|
|
|
Add('', 0); |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
constructor TCodeBlock.Create; |
|
|
|
begin |
|
|
|
inherited Create; |
|
|
|
Clear; |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
//TengShaderGeneratorArgs.TCodePart/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
@@ -204,7 +267,6 @@ 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 |
|
|
|
gfAddToPrev // add current line to previouse line |
|
|
|
); |
|
|
|
TGenFlags = set of TGenFlag; |
|
|
@@ -212,124 +274,117 @@ type |
|
|
|
var |
|
|
|
i: Integer; |
|
|
|
f: TGenFlags; |
|
|
|
line: String; |
|
|
|
cb: TCodeBlock; |
|
|
|
|
|
|
|
function GetStrOffset(const aStr: String): Integer; |
|
|
|
function GetCurrentIndent(const aStr: String): Integer; |
|
|
|
var |
|
|
|
len: Integer; |
|
|
|
begin |
|
|
|
result := 0; |
|
|
|
len := Length(aStr); |
|
|
|
while (result < len) and (aStr[result+1] in WHITESPACES) do |
|
|
|
inc(result); |
|
|
|
end; |
|
|
|
|
|
|
|
function GetOffset(const aCodePart: TCodePart): Integer; |
|
|
|
begin |
|
|
|
result := GetStrOffset(line); |
|
|
|
end; |
|
|
|
|
|
|
|
function GetMinOffset(aStartIndex: Integer): Integer; |
|
|
|
begin |
|
|
|
if (Trim(line) <> '') |
|
|
|
then result := GetStrOffset(line) |
|
|
|
else result := High(Integer); |
|
|
|
while (aStartIndex < aCode.Count) do begin |
|
|
|
if (Trim(aCode[aStartIndex]) <> '') then |
|
|
|
result := Min(result, GetStrOffset(aCode[aStartIndex])); |
|
|
|
inc(aStartIndex); |
|
|
|
end; |
|
|
|
if (result >= High(Integer)) then |
|
|
|
result := 0; |
|
|
|
if (Trim(aStr) <> '') then begin |
|
|
|
result := 1; |
|
|
|
len := Length(aStr); |
|
|
|
while (result <= len) and (aStr[result] in WHITESPACES) do |
|
|
|
inc(result); |
|
|
|
dec(result); |
|
|
|
end else |
|
|
|
result := High(Integer); |
|
|
|
end; |
|
|
|
|
|
|
|
function TrimLeftLen(const aStr: String; aLen: Integer): String; |
|
|
|
function IndentStr(const aStr: String; const aIndent: Integer): String; |
|
|
|
var |
|
|
|
i, len: Integer; |
|
|
|
begin |
|
|
|
i := 1; |
|
|
|
len := Length(aStr); |
|
|
|
while (i <= len) and (aStr[i] in WHITESPACES) and (aLen > 0) do begin |
|
|
|
inc(i); |
|
|
|
dec(aLen); |
|
|
|
end; |
|
|
|
result := Copy(aStr, i, len - i + 1); |
|
|
|
end; |
|
|
|
|
|
|
|
function PrepareStr(const aStr: String; const aOffset: Integer): String; |
|
|
|
i, l: Integer; |
|
|
|
begin |
|
|
|
if (aOffset > 0) |
|
|
|
then result := StringOfChar(' ', aOffset) + aStr |
|
|
|
else result := TrimLeftLen(aStr, -aOffset); |
|
|
|
if (aIndent < 0) then begin |
|
|
|
i := 1; |
|
|
|
l := Length(aStr); |
|
|
|
while (i <= l) and (i <= -aIndent) and (aStr[i] in WHITESPACES) do |
|
|
|
inc(i); |
|
|
|
result := copy(aStr, i, l - i + 1); |
|
|
|
end else if (aIndent > 0) then |
|
|
|
result := StringOfChar(' ', aIndent) + aStr |
|
|
|
else |
|
|
|
result := aStr; |
|
|
|
end; |
|
|
|
|
|
|
|
procedure IndentBlock(aStartIndex: Integer; const aIndent: Integer); |
|
|
|
procedure IndentBlock(aDepth, aIndent: Integer); |
|
|
|
var |
|
|
|
o: Integer; |
|
|
|
i, minCurIndent: Integer; |
|
|
|
begin |
|
|
|
o := aIndent - GetMinOffset(aStartIndex); |
|
|
|
while (aStartIndex < aCode.Count) do begin |
|
|
|
aCode[aStartIndex] := PrepareStr(aCode[aStartIndex], o); |
|
|
|
inc(aStartIndex); |
|
|
|
i := cb.Count-1; |
|
|
|
minCurIndent := High(Integer); |
|
|
|
while (i >= 0) and (cb.Depth[i] = aDepth) do begin |
|
|
|
minCurIndent := min(minCurIndent, GetCurrentIndent(cb[i])); |
|
|
|
dec(i); |
|
|
|
end; |
|
|
|
inc(i); |
|
|
|
aIndent := aIndent - minCurIndent; |
|
|
|
while (i < cb.Count) do begin |
|
|
|
cb[i] := IndentStr(cb[i], aIndent); |
|
|
|
cb.Depth[i] := cb.Depth[i] - 1; |
|
|
|
inc(i); |
|
|
|
end; |
|
|
|
if (Trim(line) <> '') then |
|
|
|
line := PrepareStr(line, o); |
|
|
|
end; |
|
|
|
|
|
|
|
procedure ProgressBlock(const aIndent: Integer); |
|
|
|
procedure ProgressBlock(const aIndent, aDepth: Integer); |
|
|
|
var |
|
|
|
s: String; |
|
|
|
cp: TCodePart; |
|
|
|
FirstLineIndex: Integer; |
|
|
|
tmp: Integer; |
|
|
|
begin |
|
|
|
FirstLineIndex := aCode.Count; |
|
|
|
while (i < fItems.Count) do begin |
|
|
|
cp := fItems[i]; |
|
|
|
inc(i); |
|
|
|
|
|
|
|
if (Trim(cb.Last) = '') then |
|
|
|
cb.Depth[cb.Count-1] := aDepth; |
|
|
|
|
|
|
|
case cp.Token of |
|
|
|
gtLineBreak: begin |
|
|
|
if (Trim(line) = '') then begin |
|
|
|
if (Trim(cb.Last) = '') then begin |
|
|
|
if (f * [gfTokenOnly, gfPrevIsEmpty] = []) then begin |
|
|
|
aCode.Add(line); |
|
|
|
Include(f, gfPrevIsEmpty); |
|
|
|
end; |
|
|
|
cb.Add('', aDepth); |
|
|
|
end else |
|
|
|
cb.Last := ''; |
|
|
|
end else begin |
|
|
|
if (gfAddToPrev in f) and not (gfCodeIsEmpty in f) |
|
|
|
then aCode[aCode.Count-1] := aCode[aCode.Count-1] + TrimLeft(line) |
|
|
|
else aCode.Add(line); |
|
|
|
if (gfAddToPrev in f) and (cb.Count >= 2) then begin |
|
|
|
cb[cb.Count-2] := cb[cb.Count-2] + TrimLeft(cb.Last); |
|
|
|
cb.Last := ''; |
|
|
|
end else |
|
|
|
cb.Add('', aDepth); |
|
|
|
Exclude(f, gfPrevIsEmpty); |
|
|
|
Exclude(f, gfCodeIsEmpty); |
|
|
|
end; |
|
|
|
Exclude(f, gfToken); |
|
|
|
Exclude(f, gfTokenOnly); |
|
|
|
Exclude(f, gfAddToPrev); |
|
|
|
line := ''; |
|
|
|
f := f - [gfToken, gfTokenOnly, gfAddToPrev]; |
|
|
|
end; |
|
|
|
|
|
|
|
gtToken: begin |
|
|
|
Include(f, gfToken); |
|
|
|
if (Trim(line) = '') then |
|
|
|
if (Trim(cb.Last) = '') then |
|
|
|
Include(f, gfTokenOnly); |
|
|
|
end; |
|
|
|
|
|
|
|
gtBlockBegin: begin |
|
|
|
Include(f, gfPrevIsEmpty); |
|
|
|
ProgressBlock(GetStrOffset(line) + cp.Indent); |
|
|
|
tmp := GetCurrentIndent(cb.Last); |
|
|
|
if (tmp <> High(Integer)) |
|
|
|
then tmp := aIndent + tmp |
|
|
|
else tmp := aIndent; |
|
|
|
if (Trim(cb.Last) <> '') then |
|
|
|
inc(tmp, 4); |
|
|
|
inc(tmp, cp.Indent); |
|
|
|
ProgressBlock(tmp, aDepth + 1); |
|
|
|
end; |
|
|
|
|
|
|
|
gtBlockEnd: begin |
|
|
|
IndentBlock(FirstLineIndex, aIndent); |
|
|
|
IndentBlock(aDepth, aIndent); |
|
|
|
exit; |
|
|
|
end; |
|
|
|
|
|
|
|
gtAppendToPrev: begin |
|
|
|
if (Trim(line) = '') and not (gfPrevIsEmpty in f) then |
|
|
|
if (Trim(cb.Last) = '') and not (gfPrevIsEmpty in f) then |
|
|
|
include(f, gfAddToPrev); |
|
|
|
end; |
|
|
|
else |
|
|
|
s := cp.Code; |
|
|
|
line := line + s; |
|
|
|
cb.Last := cb.Last + cp.Code; |
|
|
|
end; |
|
|
|
end; |
|
|
|
end; |
|
|
@@ -339,29 +394,43 @@ var |
|
|
|
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; |
|
|
|
aCode.Text := aCode.Text + s + sLineBreak + sLineBreak; |
|
|
|
end; |
|
|
|
{$ENDIF} |
|
|
|
|
|
|
|
var |
|
|
|
s, e: Integer; |
|
|
|
begin |
|
|
|
i := 0; |
|
|
|
f := [gfPrevIsEmpty, gfCodeIsEmpty]; |
|
|
|
line := ''; |
|
|
|
{$IFDEF DEBUG} |
|
|
|
GenerateDebugCode; |
|
|
|
{$ENDIF} |
|
|
|
ProgressBlock(0); |
|
|
|
|
|
|
|
i := 0; |
|
|
|
f := [gfPrevIsEmpty]; |
|
|
|
cb := TCodeBlock.Create; |
|
|
|
try |
|
|
|
ProgressBlock(0, 0); |
|
|
|
s := 0; |
|
|
|
e := cb.Count-1; |
|
|
|
while (s < cb.Count) and (Trim(cb[s]) = '') do |
|
|
|
inc(s); |
|
|
|
while (e >= 0) and (Trim(cb[e]) = '') do |
|
|
|
dec(e); |
|
|
|
for i := s to e do |
|
|
|
aCode.Add( |
|
|
|
{$IFDEF DEBUG} |
|
|
|
Format('[%02d]%s', [cb.Depth[i], cb[i]]) |
|
|
|
{$ELSE} |
|
|
|
cb[i] |
|
|
|
{$ENDIF} |
|
|
|
); |
|
|
|
finally |
|
|
|
FreeAndNil(cb); |
|
|
|
end; |
|
|
|
end; |
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
|
@@ -737,10 +806,9 @@ begin |
|
|
|
// 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, '')); |
|
|
|
csi.Items.Insert(i+0, TCodePart.Create(gtNormal, aRetType + ' ' + s)); |
|
|
|
csi.Items.Insert(i+1, TCodePart.Create(gtCommandEnd, ';')); |
|
|
|
csi.Items.Insert(i+2, TCodePart.Create(gtLineBreak, '')); |
|
|
|
|
|
|
|
// replace "return" with temp variable |
|
|
|
for cp in csi.Items do |
|
|
|