Repository navigation
XSLT generator: generated code faster than XslCompiledTransform - #43
Open
simonebortolin wants to merge 14 commits into
Open
simonebortolin wants to merge 14 commits into
simonebortolin wants to merge 14 commits into
Conversation
ctop.xsl, which main runs for Content MathML, is compiled like the other stylesheets (CtopStylesheet) and compared with XslCompiledTransform on the equations of tests/data/contentmathml. The tests of OmmlAstralTests that pinned the UTF-16 counting of XslCompiledTransform pin what they said counting code points gives. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
…ransform [no-new-version] Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
…string-length() without lists The map of a translate() with constant arguments is a static table, and that of the others is kept from one call to the next; a text that nothing is replaced in is returned as it is. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
…as strings A location path is compiled to loops over the nodes (first child and next sibling, the node test inlined, names compared as static XName fields), in the method that uses it or in a method of its own whose parameters are what the expression reads; no node-set is built for a test, the string value of the first node, a count or a comparison, and position() and last() are counted only by the predicates that read them. xsl:for-each and xsl:apply-templates walk the nodes without a list unless the content, or a template of the mode, reads their number. The stylesheet is compiled until nothing new is learnt of its templates: the parameters of a named template have the type of the values they are given, and a template is given the context node, position and size only if it reads them. A variable whose content only writes text is a string, written as an expression when it is only values and choices, and a global string that does not depend on the input is computed once. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
… are needed The open element is found by its parent, the text between two nodes is kept as the string it mostly is, its markup is built only once some is written with disable-output-escaping, and a short whole number is read without a copy. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
…ns of unknown types without LINQ A variable or a parameter whose node-set has at most one node (the context node, a parent, a step with a position) holds the node or null, not a list. The nodes of a path from a list are sorted only when the list has more than one node. The comparison of values whose type is known at run time only walks the nodes without iterators, and takes a string or a number as it is. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
…ces read without a parser The many rules of an element whose pattern asks for a child with a text (the characters of MTEF, each with its code) are found by a switch on the text of that child, when the element has one, and tried in order otherwise. Text written with disable-output-escaping that is only text and references to characters is read as it is, not by an XML parser. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
…ces after a comma (#37) Four equations that read from UnicodeMath and were written as text that read back to another equation: - a script of a matrix in brackets: ⒨(𝑎&𝑏@𝑐&𝑑)² read the ² apart from the matrix (and ^−1 did not parse); the matrix is grouped, 〖⒨(…)〗², as the other bases that a script would not apply to whole - a function in a denominator: 𝑎/ sin𝛼 read as a slash, the space after the bar ending the fraction; the space is not written, 𝑎/sin𝛼 - a denominator that ends with a script before an operand: 1/4𝜋𝜀₀ 𝑞₁𝑞₂/𝑟² took 𝑞₁𝑞₂/𝑟² into the denominator, the space ending the script and not the denominator; it is in parentheses, 1/(4𝜋𝜀₀) (but not after superscript digits, 𝜕²/𝜕𝑥² 𝜓, which a space ends, nor before an operator) - ", " (a comma and two spaces, a space of ½ em after the comma in the grammar) was read as an empty <mo/>, which nothing writes: it is the space of that width, U+2002, as ", " reads Claude-Session: https://claude.ai/code/session_01SyVio8afJsGwHW9i5v5HDs Co-authored-by: Claude <noreply@anthropic.com>
… XslCompiledTransform [no-new-version] The axes, the predicates that count, the node-sets as variables and parameters, the comparisons between the types, the parameters of mixed types, the rules found by the text of a child: beyond what the stylesheets of the library use of them on the corpora. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
Not yet verified to build and pass on both target frameworks. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ
…de/gracious-mayer-wl7f46 # Conflicts: # tests/SharpEquations.Tests/Omml/OmmlAstralTests.cs
simonebortolin
marked this pull request as ready for review
November 11, 2026 21:20
|
Pre-release NuGet package of 0f5adc1. Updated on every push, deleted when this PR is closed. |
This branch has not been deployed
This file contains hidden or 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
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.
Stacked on #5 (the XSLT → C# source generator that makes the library Native AOT compatible): it optimises the generated code and its run time.
mainis merged in, so the diff also shows the three files of #37, which #5 does not have yet.What changes
translate()builds its map once;substring()andstring-length()work without lists.char[mt_code_value='0x…'](341 inmtef2mml.xsl) are found by aswitchon the child's text; character references are decoded without a parser.StylesheetBenchmarksmeasures the stylesheets alone, compiled and run byXslCompiledTransform.conformance.xsl, a test stylesheet of what the generator compiles (axes, positional predicates, node-set and mixed-type parameters, cross-type comparisons, keyed dispatch), is run compiled and byXslCompiledTransform.Numbers
BenchmarkDotNet
StylesheetBenchmarks, short job, net10.0, time and allocation per whole corpus. The short job is noisy, so the ratios are approximate. Measured before the last merge of #5 andmain.XslCompiledTransformctop)Verification
dotnet test --solution SharpEquations.slnxon the merged head: 6994 of 6994 pass, on net10.0 and on net8.0 (the netstandard2.0 build).CompiledStylesheetTestsfinds the output of the four stylesheets and of the conformance stylesheet identical toXslCompiledTransform. As in XSLT stylesheets compiled to C# by a source generator: Native AOT #5, inputs with characters outside the basic plane are left out of that comparison.followingaxis,id(),xsl:sort) still fails the build withXSLT001: checked by hand, there is no automated test for it.To confirm
InternalsVisibleTo("SharpEquations.Benchmarks")was added so that the benchmarks reach the stylesheets.OmmlAstralTestsis the version of XSLT stylesheets compiled to C# by a source generator: Native AOT #5.🤖 Generated with Claude Code
https://claude.ai/code/session_01Q8QQiasbLr6WtXXCEP1zrJ