Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/Sempare.Template.Evaluate.pas
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,10 @@ procedure TEvaluationTemplateVisitor.Visit(const AStmt: IForInStmt);

while not LDataSetEOFProperty.GetValue(LObj).AsBoolean and ((LLimit = -1) or (LLoops < LLimit)) do
begin
FStackFrames.peek[LVariableName] := LIdx;
if AStmt.ForOp = foIn then
FStackFrames.peek[LVariableName] := LIdx - 1
else
FStackFrames.peek[LVariableName] := LLoopExpr;
if HandleLoop then
break;
LDataSetNextMethod.Invoke(LObj, []);
Expand All @@ -521,6 +524,7 @@ procedure TEvaluationTemplateVisitor.Visit(const AStmt: IForInStmt);
LValue: TValue;
LValue2: TValue;
LRaiseIfMissing: boolean;
LIdx: integer;
begin
if LLoopExprType.AsInstance.MetaclassType.InheritsFrom(TDataSet) then
begin
Expand All @@ -534,6 +538,7 @@ procedure TEvaluationTemplateVisitor.Visit(const AStmt: IForInStmt);
if LEnumValue.IsEmpty then
RaiseErrorRes(AStmt, @SValueIsNotEnumerable);
LEnumObj := LEnumValue.AsObject;
LIdx := 0;
try
LLoopExprType := FContext.RttiContext().GetType(LEnumObj.ClassType);
LEnumMoveNextMethod := LLoopExprType.GetMethod('MoveNext');
Expand All @@ -543,9 +548,14 @@ procedure TEvaluationTemplateVisitor.Visit(const AStmt: IForInStmt);
begin
LValue := LEnumCurrentProperty.GetValue(LEnumObj);
TryDeref(AStmt, LValue, LRaiseIfMissing, FContext, LValue2);
FStackFrames.peek[LVariableName] := LValue2;

if AStmt.ForOp = foIn then
FStackFrames.peek[LVariableName] := LIdx
else
FStackFrames.peek[LVariableName] := LValue2;
if HandleLoop then
break;
inc(LIdx);
end;
finally
LEnumObj.Free;
Expand Down
6 changes: 4 additions & 2 deletions tests/Sempare.Template.Test.pas
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ procedure TTestTemplate.TestList;
Assert.AreEqual('2', Template.Eval('<% _.count %>', LList));
Assert.AreEqual('2', Template.Eval('<% data.count %>', LContainer));
Assert.AreEqual('System.Generics.Collections.TObjectList<Sempare.Template.Test.TTestClass>', Template.Eval('<% typeof(data) %>', LContainer));
Assert.AreEqual(' a b', Template.Eval('<% for x in data %> <% x.data %><% end %>', LContainer));
Assert.AreEqual(' 0 1', Template.Eval('<% for x in data %> <% x %><% end %>', LContainer));
Assert.AreEqual(' a b', Template.Eval('<% for x of data %> <% x.data %><% end %>', LContainer));
finally
LList.free;
end;
Expand Down Expand Up @@ -858,7 +859,8 @@ procedure TTestTemplate.TestUnderscoreIn;
L := TList<string>.Create;
try
L.AddRange(['1', '2', '3']);
Assert.AreEqual('123', Template.Eval('<% for v in _ %><% v %><% end %>', L));
Assert.AreEqual('012', Template.Eval('<% for v in _ %><% v %><% end %>', L));
Assert.AreEqual('123', Template.Eval('<% for v of _ %><% v %><% end %>', L));
finally
L.free;
end;
Expand Down
82 changes: 80 additions & 2 deletions tests/Sempare.Template.TestFor.pas
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,38 @@ procedure TTestTemplateFor.TestDataSet;
var
ds: TDataSet;
begin
// traditional
ds := CreateMockUsersTable();
try
Assert.AreEqual('joe pete jane ', //
Template.Eval('<% for i in _ %><% _[''name''] %> <%end%>', ds));
finally
ds.Free;
end;
// index in
ds := CreateMockUsersTable();
try
Assert.AreEqual('0 1 2 ', //
Template.Eval('<% for i in _ %><% i %> <%end%>', ds));
finally
ds.Free;
end;
// index of
ds := CreateMockUsersTable();
try
Assert.AreEqual('joe pete jane ', //
Template.Eval('<% for i of _ %><% i[''name''] %> <%end%>', ds));
finally
ds.Free;
end;

end;

procedure TTestTemplateFor.TestDataSetWithEvent;
var
ds: TDataSet;
begin
// traditional
ds := CreateMockUsersTable();
try
Assert.AreEqual('<ul><li>joe</li><li>pete</li><li>jane</li></ul>', //
Expand All @@ -175,6 +194,40 @@ procedure TTestTemplateFor.TestDataSetWithEvent;
finally
ds.Free;
end;

// using index in
ds := CreateMockUsersTable();
try
Assert.AreEqual('<ul><li>0</li><li>1</li><li>2</li></ul>', //
Template.Eval('<% for i in _ %><li><% i %></li><% onbegin%><ul><%onend%></ul><%end%>', ds));

ds.Delete();
ds.Delete();
ds.Delete();

Assert.AreEqual('<h1>No values</h1>', //
Template.Eval('<% for i in _ %><li><% i %></li><% onbegin%><ul><%onend%></ul><% onempty%><h1>No values</h1><%end%>', ds));

finally
ds.Free;
end;

// using index of
ds := CreateMockUsersTable();
try
Assert.AreEqual('<ul><li>joe</li><li>pete</li><li>jane</li></ul>', //
Template.Eval('<% for i of _ %><li><% i[''name''] %></li><% onbegin%><ul><%onend%></ul><%end%>', ds));

ds.Delete();
ds.Delete();
ds.Delete();

Assert.AreEqual('<h1>No values</h1>', //
Template.Eval('<% for i in _ %><li><% [''name''] %></li><% onbegin%><ul><%onend%></ul><% onempty%><h1>No values</h1><%end%>', ds));

finally
ds.Free;
end;
end;

procedure TTestTemplateFor.TestDataSetCount;
Expand Down Expand Up @@ -232,6 +285,9 @@ TForIn = record
try
x.range.AddRange([1, 10, 100]);
c := Template.parse('<% for i in range %> <% i %> <% end %>');
Assert.AreEqual(' 0 1 2 ', Template.Eval(c, x));

c := Template.parse('<% for i of range %> <% i %> <% end %>');
Assert.AreEqual(' 1 10 100 ', Template.Eval(c, x));
finally
x.range.Free;
Expand All @@ -250,16 +306,26 @@ TForIn = record
x.range := TList<integer>.Create;
try
x.range.AddRange([3, 5, 7, 9]);

c := Template.parse('<% for i in range %><li><%i%></li><%onbegin%><ul><%onend%></ul><%onempty%>empty<%end%>');
Assert.AreEqual('<ul><li>0</li><li>1</li><li>2</li><li>3</li></ul>', Template.Eval(c, x));

c := Template.parse('<% for i of range %><li><%i%></li><%onbegin%><ul><%onend%></ul><%onempty%>empty<%end%>');
Assert.AreEqual('<ul><li>3</li><li>5</li><li>7</li><li>9</li></ul>', Template.Eval(c, x));

c := Template.parse('<% for i in range %><%i%><%betweenitems%>|<%onbegin%>begin<%onend%>end<%onempty%>empty<%end%>');
Assert.AreEqual('begin0|1|2|3end', Template.Eval(c, x));

c := Template.parse('<% for i of range %><%i%><%betweenitems%>|<%onbegin%>begin<%onend%>end<%onempty%>empty<%end%>');
Assert.AreEqual('begin3|5|7|9end', Template.Eval(c, x));

x.range.Clear;
c := Template.parse('<% for i in range %><li><%i%></li><%onbegin%><ul><%onend%></ul><%onempty%>empty<% end %>');
Assert.AreEqual('empty', Template.Eval(c, x));

c := Template.parse('<% for i of range %><li><%i%></li><%onbegin%><ul><%onend%></ul><%onempty%>empty<% end %>');
Assert.AreEqual('empty', Template.Eval(c, x));

finally
x.range.Free;
end;
Expand Down Expand Up @@ -323,7 +389,11 @@ TForIn = record
try
x.range.AddRange([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
c := Template.parse('<% for i in range offset 5 %> <% i %> <% end %>');
Assert.AreEqual(' 5 6 7 8 9 ', Template.Eval(c, x));

c := Template.parse('<% for i of range offset 5 %> <% i %> <% end %>');
Assert.AreEqual(' 6 7 8 9 10 ', Template.Eval(c, x));

finally
x.range.Free;
end;
Expand All @@ -342,7 +412,11 @@ TForIn = record
try
x.range.AddRange([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
c := Template.parse('<% for i in range offset 5 limit 2 %> <% i %> <% end %>');
Assert.AreEqual(' 5 6 ', Template.Eval(c, x));

c := Template.parse('<% for i of range offset 5 limit 2 %> <% i %> <% end %>');
Assert.AreEqual(' 6 7 ', Template.Eval(c, x));

finally
x.range.Free;
end;
Expand Down Expand Up @@ -465,7 +539,9 @@ procedure TTestTemplateFor.TestStructure;
info := TList<TInfo>.Create;
try
info.AddRange([TInfo.Create('conrad', 10), TInfo.Create('christa', 20)]);
Assert.AreEqual(' conrad 10 christa 20', Template.Eval('<%for i in _ %> <% i.name %> <% i.age %><%end%>', info));
Assert.AreEqual(' 0 1', Template.Eval('<%for i in _ %> <% i%><%end%>', info));

Assert.AreEqual(' conrad 10 christa 20', Template.Eval('<%for i of _ %> <% i.name %> <% i.age %><%end%>', info));
finally
info.Free;
end;
Expand All @@ -480,7 +556,9 @@ procedure TTestTemplateFor.TestForInDict;
try
LDict.Add('a', 1);
LDict.Add('b', 2);
Assert.AreEqual(' b 2 a 1', Template.Eval('<%for i in _ %> <% i.key %> <% i.value %><%end%>', LDict));
Assert.AreEqual(' 0 1', Template.Eval('<%for i in _ %> <% i %><%end%>', LDict));

Assert.AreEqual(' b 2 a 1', Template.Eval('<%for i of _ %> <% i.key %> <% i.value %><%end%>', LDict));
finally
LDict.Free;
end;
Expand Down
2 changes: 1 addition & 1 deletion tests/Sempare.Template.TestInclude.pas
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ procedure TTestTemplateInclude.TestInclude;

c := Template.parse( //
'<% suffix := ''er''%><% include (''head'' + suffix) %>' + //
'<%for v in content %>' + '<% v %>' + //
'<%for v of content %>' + '<% v %>' + //
'<% end %>' + //
'<% include (''foot'' + suffix) %>');

Expand Down
61 changes: 59 additions & 2 deletions tests/Sempare.Template.TestJson.pas
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,18 @@ TTestTemplateJson = class
[test]
procedure TestJsonDerefAV;

[test]
procedure TestJsonIn;

[test]
procedure TestJsonOf;

end;

implementation

uses
System.SysUtils,
Sempare.Template.JSON,
Sempare.Template;

Expand Down Expand Up @@ -119,13 +126,38 @@ procedure TTestTemplateJson.TestJsonEmptyArray;
o.Free;
end;

procedure TTestTemplateJson.TestJsonIn;
var
LScript: string;
LResult: string;
LExpect: string;
LJsonArray: TJSONArray;
begin
LScript := //
'<% arr := [5,4,3]; ' + sLineBreak + //
sLineBreak + //
'for x in arr ; x ; betweenitems %>, <% end %>' + sLineBreak; //
LExpect := '0, 1, 2' + sLineBreak;
LResult := Template.Eval(LScript);
Assert.AreEqual(LExpect, LResult);

LJsonArray := TJsonValue.ParseJSONValue('[5,4,3]') as TJSONArray;
LScript := '<% for x in _ ; x ; betweenitems %>, <% end %>' + sLineBreak;
try
LResult := Template.Eval(LScript, LJsonArray);
Assert.AreEqual(LExpect, LResult);
finally
LJsonArray.Free;
end;
end;

procedure TTestTemplateJson.TestJsonArray;
var
o: TJsonValue;
begin
o := TJsonValue.ParseJSONValue('[1,2,3,4,5]');
Assert.AreEqual('1 2 3 4 5 ', Template.Eval('<% for i in _ %><% i %> <% end %>', o));

Assert.AreEqual('0 1 2 3 4 ', Template.Eval('<% for i in _ %><% i %> <% end %>', o));
Assert.AreEqual('1 2 3 4 5 ', Template.Eval('<% for i of _ %><% i %> <% end %>', o));
o.Free;
end;

Expand All @@ -146,6 +178,31 @@ procedure TTestTemplateJson.TestJsonObject;
o.Free;
end;

procedure TTestTemplateJson.TestJsonOf;
var
LScript: string;
LResult: string;
LExpect: string;
LJsonArray: TJSONArray;
begin
LScript := //
'<% arr := [5,4,3]; ' + sLineBreak + //
sLineBreak + //
'for x of arr ; x ; betweenitems %>, <% end %>' + sLineBreak; //
LExpect := '5, 4, 3' + sLineBreak;
LResult := Template.Eval(LScript);
Assert.AreEqual(LExpect, LResult);

LJsonArray := TJsonValue.ParseJSONValue('[5,4,3]') as TJSONArray;
LScript := '<% for x of _ ; x ; betweenitems %>, <% end %>' + sLineBreak;
try
LResult := Template.Eval(LScript, LJsonArray);
Assert.AreEqual(LExpect, LResult);
finally
LJsonArray.Free;
end;
end;

procedure TTestTemplateJson.TestParseJson;
begin
Assert.AreEqual('123.45', Template.Eval('<% ParseJson("123.45") %>'));
Expand Down