Skip to content

Commit

Permalink
Optimize template for both simple and dynamic documents.
Browse files Browse the repository at this point in the history
  • Loading branch information
Remi Caput committed Feb 20, 2016
1 parent cc44992 commit fe78c4e
Show file tree
Hide file tree
Showing 12 changed files with 113 additions and 47 deletions.
3 changes: 3 additions & 0 deletions Cottle.Test/src/DocumentTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ public void CommandForValue (string name, string source, string body, string exp
[TestCase ("1", "a|elif 1:b|else:c", "a")]
[TestCase ("0", "a|elif 1:b|else:c", "b")]
[TestCase ("0", "a|elif 0:b|else:c", "c")]
[TestCase ("1 + 0", "a|elif 1 + 0:b|else:c", "a")]
[TestCase ("0 + 0", "a|elif 1 + 0:b|else:c", "b")]
[TestCase ("0 + 0", "a|elif 0 + 0:b|else:c", "c")]
public void CommandIf (string condition, string body, string expected)
{
this.AssertRender ("{if " + condition + ":" + body + "}", expected);
Expand Down
2 changes: 2 additions & 0 deletions Cottle/Cottle.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
<Compile Include="src\Maps\EmptyMap.cs" />
<Compile Include="src\Maps\HashMap.cs" />
<Compile Include="src\Maps\MixMap.cs" />
<Compile Include="src\ParserFactory.cs" />
<Compile Include="src\Parsers\DefaultParser.cs" />
<Compile Include="src\Parsers\Default\Lexem.cs" />
<Compile Include="src\Parsers\Default\LexemCursor.cs" />
Expand All @@ -109,6 +110,7 @@
<Compile Include="src\Parsers\PostParser.cs" />
<Compile Include="src\Parsers\Post\IOptimizer.cs" />
<Compile Include="src\Parsers\Post\Optimizers\AbstractOptimizer.cs" />
<Compile Include="src\Parsers\Post\Optimizers\IfOptimizer.cs" />
<Compile Include="src\Parsers\Post\Optimizers\ConstantMapOptimizer.cs" />
<Compile Include="src\Parsers\Post\Optimizers\ReturnOptimizer.cs" />
<Compile Include="src\Settings\CustomSetting.cs" />
Expand Down
2 changes: 1 addition & 1 deletion Cottle/Cottle.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<iconUrl>https://raw.github.com/r3c/cottle/master/icon.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<releaseNotes>Add "defined" and "type" builtin functions.</releaseNotes>
<releaseNotes>Optimize template for both simple and dynamic documents.</releaseNotes>
<copyright>$copyright$</copyright>
<tags>Template Templating Engine HTML JavaScript Email</tags>
</metadata>
Expand Down
4 changes: 2 additions & 2 deletions Cottle/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// Vous pouvez spécifier toutes les valeurs ou indiquer les numéros de build et de révision par défaut
// en utilisant '*', comme indiqué ci-dessous :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.3.1.3")]
[assembly: AssemblyFileVersion("1.3.1.3")]
[assembly: AssemblyVersion("1.3.2.0")]
[assembly: AssemblyFileVersion("1.3.2.0")]
6 changes: 6 additions & 0 deletions Cottle/src/Command.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ namespace Cottle
{
class Command
{
#region Attributes / Static

public static readonly Command NoOp = new Command { Type = CommandType.None };

#endregion

#region Attributes / Instance

public string[] Arguments;
Expand Down
1 change: 1 addition & 0 deletions Cottle/src/CommandType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace Cottle
{
enum CommandType
{
None,
AssignFunction,
AssignValue,
Composite,
Expand Down
16 changes: 1 addition & 15 deletions Cottle/src/Documents/DynamicDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
using System.IO;
using System.Linq;
using Cottle.Documents.Dynamic;
using Cottle.Parsers;
using Cottle.Parsers.Post;
using Cottle.Parsers.Post.Optimizers;
using Cottle.Settings;

namespace Cottle.Documents
Expand All @@ -27,18 +24,7 @@ public sealed class DynamicDocument : AbstractDocument

public DynamicDocument (TextReader reader, ISetting setting)
{
IParser parser;

parser = new DefaultParser (setting.BlockBegin, setting.BlockContinue, setting.BlockEnd, setting.Escape);

if (setting.Optimize)
{
parser = new PostParser (parser, new IOptimizer[]
{
new ConstantMapOptimizer (),
new ReturnOptimizer ()
});
}
IParser parser = ParserFactory.BuildParser (setting);

this.main = new Function (new string[0], parser.Parse (reader), setting.Trimmer, string.Empty);
}
Expand Down
28 changes: 12 additions & 16 deletions Cottle/src/Documents/SimpleDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Cottle.Documents.Simple;
using Cottle.Documents.Simple.Evaluators;
using Cottle.Documents.Simple.Nodes;
using Cottle.Parsers;
using Cottle.Settings;

namespace Cottle.Documents
Expand All @@ -29,14 +28,11 @@ public sealed class SimpleDocument : AbstractDocument

public SimpleDocument (TextReader reader, ISetting setting)
{
IParser parser;
Command root;

parser = new DefaultParser (setting.BlockBegin, setting.BlockContinue, setting.BlockEnd, setting.Escape);
root = parser.Parse (reader);
IParser parser = ParserFactory.BuildParser (setting);
Command root = parser.Parse (reader);

this.renderer = this.CompileCommand (root, setting.Trimmer);
this.setting = setting;
this.renderer = this.CompileCommand (root);
}

public SimpleDocument (TextReader reader) :
Expand Down Expand Up @@ -91,15 +87,15 @@ public string Source ()

#region Methods / Private

private INode CompileCommand (Command command)
private INode CompileCommand (Command command, Trimmer trimmer)
{
List<KeyValuePair<IEvaluator, INode>> branches;
List<INode> nodes;

switch (command.Type)
{
case CommandType.AssignFunction:
return new AssignFunctionNode (command.Name, command.Arguments, this.CompileCommand (command.Body), command.Mode);
return new AssignFunctionNode (command.Name, command.Arguments, this.CompileCommand (command.Body, trimmer), command.Mode);

case CommandType.AssignValue:
return new AssignValueNode (command.Name, this.CompileExpression (command.Operand), command.Mode);
Expand All @@ -108,9 +104,9 @@ private INode CompileCommand (Command command)
nodes = new List<INode> ();

for (; command.Type == CommandType.Composite; command = command.Next)
nodes.Add (this.CompileCommand (command.Body));
nodes.Add (this.CompileCommand (command.Body, trimmer));

nodes.Add (this.CompileCommand (command));
nodes.Add (this.CompileCommand (command, trimmer));

return new CompositeNode (nodes);

Expand All @@ -121,24 +117,24 @@ private INode CompileCommand (Command command)
return new EchoNode (this.CompileExpression (command.Operand));

case CommandType.For:
return new ForNode (this.CompileExpression (command.Operand), command.Key, command.Name, this.CompileCommand (command.Body), command.Next != null ? this.CompileCommand (command.Next) : null);
return new ForNode (this.CompileExpression (command.Operand), command.Key, command.Name, this.CompileCommand (command.Body, trimmer), command.Next != null ? this.CompileCommand (command.Next, trimmer) : null);

case CommandType.If:
branches = new List<KeyValuePair<IEvaluator, INode>> ();

for (; command != null && command.Type == CommandType.If; command = command.Next)
branches.Add (new KeyValuePair<IEvaluator, INode> (this.CompileExpression (command.Operand), this.CompileCommand (command.Body)));
branches.Add (new KeyValuePair<IEvaluator, INode> (this.CompileExpression (command.Operand), this.CompileCommand (command.Body, trimmer)));

return new IfNode (branches, command != null ? this.CompileCommand (command) : null);
return new IfNode (branches, command != null ? this.CompileCommand (command, trimmer) : null);

case CommandType.Literal:
return new LiteralNode (this.setting.Trimmer (command.Text));
return new LiteralNode (trimmer (command.Text));

case CommandType.Return:
return new ReturnNode (this.CompileExpression (command.Operand));

case CommandType.While:
return new WhileNode (this.CompileExpression (command.Operand), this.CompileCommand (command.Body));
return new WhileNode (this.CompileExpression (command.Operand), this.CompileCommand (command.Body, trimmer));

default:
return new LiteralNode (string.Empty);
Expand Down
29 changes: 29 additions & 0 deletions Cottle/src/ParserFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using Cottle.Parsers;
using Cottle.Parsers.Post;
using Cottle.Parsers.Post.Optimizers;

namespace Cottle
{
static class ParserFactory
{
public static IParser BuildParser (ISetting setting)
{
IParser parser;

parser = new DefaultParser (setting.BlockBegin, setting.BlockContinue, setting.BlockEnd, setting.Escape);

if (setting.Optimize)
{
parser = new PostParser (parser, new IOptimizer[]
{
ConstantMapOptimizer.Instance,
IfOptimizer.Instance,
ReturnOptimizer.Instance
});
}

return parser;
}
}
}
30 changes: 17 additions & 13 deletions Cottle/src/Parsers/Post/Optimizers/ConstantMapOptimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ namespace Cottle.Parsers.Post.Optimizers
/// </summary>
class ConstantMapOptimizer : AbstractOptimizer
{
#region Attributes
#region Attributes / Static

public static readonly ConstantMapOptimizer Instance = new ConstantMapOptimizer ();

#endregion

#region Attributes / Instance

private static readonly Predicate<ExpressionElement> constants = (e) => e.Key.Type == ExpressionType.Constant && e.Value.Type == ExpressionType.Constant;

Expand All @@ -20,21 +26,19 @@ public override Expression Optimize (Expression expression)
{
KeyValuePair<Value, Value>[] pairs;

if (expression.Type == ExpressionType.Map && Array.TrueForAll (expression.Elements, ConstantMapOptimizer.constants))
{
pairs = new KeyValuePair<Value, Value>[expression.Elements.Length];
if (expression.Type != ExpressionType.Map || !Array.TrueForAll (expression.Elements, ConstantMapOptimizer.constants))
return expression;

for (int i = expression.Elements.Length; i-- > 0; )
pairs[i] = new KeyValuePair<Value, Value> (expression.Elements[i].Key.Value, expression.Elements[i].Value.Value);
pairs = new KeyValuePair<Value, Value>[expression.Elements.Length];

return new Expression
{
Type = ExpressionType.Constant,
Value = pairs
};
}
for (int i = expression.Elements.Length; i-- > 0; )
pairs[i] = new KeyValuePair<Value, Value> (expression.Elements[i].Key.Value, expression.Elements[i].Value.Value);

return expression;
return new Expression
{
Type = ExpressionType.Constant,
Value = pairs
};
}

#endregion
Expand Down
33 changes: 33 additions & 0 deletions Cottle/src/Parsers/Post/Optimizers/IfOptimizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;

namespace Cottle.Parsers.Post.Optimizers
{
/// <summary>
/// Simplify "if" command with constant condition.
/// </summary>
class IfOptimizer : AbstractOptimizer
{
#region Attributes

public static readonly IfOptimizer Instance = new IfOptimizer ();

#endregion

#region Methods

public override Command Optimize (Command command)
{
while (command != null && command.Type == CommandType.If && command.Operand.Type == ExpressionType.Constant)
{
if (command.Operand.Value.AsBoolean)
return command.Body;

command = command.Next;
}

return command ?? Command.NoOp;
}

#endregion
}
}
6 changes: 6 additions & 0 deletions Cottle/src/Parsers/Post/Optimizers/ReturnOptimizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ namespace Cottle.Parsers.Post.Optimizers
/// </summary>
class ReturnOptimizer : AbstractOptimizer
{
#region Attributes

public static readonly ReturnOptimizer Instance = new ReturnOptimizer ();

#endregion

#region Methods

public override Command Optimize (Command command)
Expand Down

0 comments on commit fe78c4e

Please sign in to comment.