-
-
Notifications
You must be signed in to change notification settings - Fork 178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compilation support #627
Draft
sebastienros
wants to merge
12
commits into
main
Choose a base branch
from
sebros/compilable
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Compilation support #627
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@lahma I hope to get your attention, very challenging work |
Thanks for the heads up, a very interesting feature. I'm just afraid that I might have too much on my plate already... |
The main branch has been updated to include the Visitor pattern from this PR. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
This is a PR showing the current progress on Liquid compilation support. It doesn't work but this needs to be saved to I salvaged it from my laptop before it's too late. I wrote this a year ago and I don't remember much of the details of the implementation, I will ty to write it down as I re-understand how everything works.
The idea is that currently Fluid parses a template to generate an AST (
IFluidTemplate
). This AST is processed by evaluating all its statements and "writing" them on aTextWriter
to render it. Many things have to be checked or computed every time the AST is evaluated, boolean expressions, math operations, for loops, ... It also has some overhead because of stack depths and extra method calls. Compilation helps with rendering performance as some conditions can be evaluated once at compiled time to generate the code that needs to be executed. It can also remove the need of reflection to access properties. Finally it allows to generate compiled templates statically if the template is known (strongly typed model) at the project compile time, even though we can still compile dynamically a random template.Part of this PR is the creation of a visitor pattern resembling the one in Roslyn (and Esprima-dotnet) that allows to alter the AST. This could be something that is extracted before the PR is finalized as it could be useful even today. This was done to be able to move the compilation code out of each AST element.
This PR contains a source code generator project that allows to create compiled templates statically. I don't remember if it works, it might since the code is there.
The remaining work consists of implementing the
Visit
for each AST node type in theAstCompiler
class. This means generating the source code that will render the template once compiled.Once the work is done, Fluid will be the fastest Liquid templates parser, will be able to interpret template quickly, detect syntax errors and optimizations (visitor) and compile templates for the fastest rendering experience possible (even compared to Razor).
How to work with this branch:
FluidTemplate.RenderAsync
is patched to support automatic compilation. There is a propertyTemplateOptions.TemplateCompilationThreshold
that will trigger the compilation automatically when a template is rendered more than that number of times. It's set to 1 such that templates are always compiled automatically on the first use. This way running the tests will run the compiled version always. I suggest trying theTemplateTests
class, a nice test beingShouldNotEncodeBlocks
. The generated code is overwriting%TEMP%\fluid.cs
every time.How do use visitors to detect specific patterns in a template:
Check how
IdentifierIsAccessedVisitor
can visit eachMemberExpression
to detect if the first segment matches a specific identifier. If one does then this identifier is used somewhere in the template.Another example of such visitor is
ContinueOffsetVisitor
which will tell if aForStatement
has a continue offset behavior.These visitors let us know if we can omit specific construct once and for all. In the case of
for
loops knowing that theforloop
property is not used anywhere allows the final compiled code to omit the creation and tracking of theforloop
object (Index
,First
,Last
... properties).NB: this optimization could also be added to the interpreter when visitors are available.
TODO:
main
. NB: It's not, but shouldn't be hard to get it back. We might want to extract some of the things directly tomain
too, for instance visitors and the model changes (public types, public properties).sebros/member_refactor
branch which has the next commit I was working on is supposed to do. Probably found some issues with strongly typed member access.