# coalescing URL: /api/compiler/coalescing/ Section: compiler -------------------------------------------------------------------------------- coalescing - Kida window.BENGAL_THEME_DEFAULTS = { appearance: 'light', palette: 'brown-bengal' }; window.Bengal = window.Bengal || {}; window.Bengal.enhanceBaseUrl = '/kida/assets/js/enhancements'; window.Bengal.watchDom = true; window.Bengal.debug = false; window.Bengal.enhanceUrls = { 'toc': '/kida/assets/js/enhancements/toc.632a9783.js', 'docs-nav': '/kida/assets/js/enhancements/docs-nav.57e4b129.js', 'tabs': '/kida/assets/js/enhancements/tabs.aac9e817.js', 'lightbox': '/kida/assets/js/enhancements/lightbox.1ca22aa1.js', 'interactive': '/kida/assets/js/enhancements/interactive.fc077855.js', 'mobile-nav': '/kida/assets/js/enhancements/mobile-nav.d991657f.js', 'action-bar': '/kida/assets/js/enhancements/action-bar.d62417f4.js', 'copy-link': '/kida/assets/js/enhancements/copy-link.7d9a5c29.js', 'data-table': '/kida/assets/js/enhancements/data-table.1f5bc1eb.js', 'lazy-loaders': '/kida/assets/js/enhancements/lazy-loaders.a5c38245.js', 'holo': '/kida/assets/js/enhancements/holo.ee13c841.js', 'link-previews': '/kida/assets/js/enhancements/link-previews.8d906535.js' }; (function () { try { var defaults = window.BENGAL_THEME_DEFAULTS || { appearance: 'system', palette: '' }; var defaultAppearance = defaults.appearance; if (defaultAppearance === 'system') { defaultAppearance = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'; } var storedTheme = localStorage.getItem('bengal-theme'); var storedPalette = localStorage.getItem('bengal-palette'); var theme = storedTheme ? (storedTheme === 'system' ? defaultAppearance : storedTheme) : defaultAppearance; var palette = storedPalette ?? defaults.palette; document.documentElement.setAttribute('data-theme', theme); if (palette) { document.documentElement.setAttribute('data-palette', palette); } } catch (e) { document.documentElement.setAttribute('data-theme', 'light'); } })(); { "prerender": [ { "where": { "and": [ { "href_matches": "/docs/*" }, { "not": { "selector_matches": "[data-external], [target=_blank], .external" } } ] }, "eagerness": "conservative" } ], "prefetch": [ { "where": { "and": [ { "href_matches": "/*" }, { "not": { "selector_matches": "[data-external], [target=_blank], .external" } } ] }, "eagerness": "conservative" } ] } Skip to main content Magnifying Glass ESC Recent Clear Magnifying Glass No results for "" Start typing to search... ↑↓ Navigate ↵ Open ESC Close Powered by Lunr )彡 DocumentationInfoAboutArrow ClockwiseGet StartedCodeSyntaxTerminalUsageNoteTutorialsStarburstExtendingBookmarkReferenceTroubleshootingReleasesDevGitHubKida API Reference Magnifying Glass Search ⌘K Palette Appearance Chevron Down Mode Monitor System Sun Light Moon Dark Palette Snow Lynx Brown Bengal Silver Bengal Charcoal Bengal Blue Bengal List )彡 Magnifying Glass Search X Close Documentation Caret Down Info About Arrow Clockwise Get Started Code Syntax Terminal Usage Note Tutorials Starburst Extending Bookmark Reference Troubleshooting Releases Dev Caret Down GitHub Kida API Reference Palette Appearance Chevron Down Mode Monitor System Sun Light Moon Dark Palette Snow Lynx Brown Bengal Silver Bengal Charcoal Bengal Blue Bengal Kida API Reference Caret Right Analysis analyzer cache config dependencies landmarks metadata purity roles Caret Right Compiler Caret Right Statements basic control_flow functions special_blocks template_structure variables _protocols coalescing core expressions utils Caret Right Environment core exceptions filters loaders protocols registry tests Caret Right Parser Caret Right Blocks control_flow core functions special_blocks template_structure variables _protocols core errors expressions statements tokens Caret Right Utils html lru_cache workers _types bytecode_cache kida lexer nodes template tstring Kida API ReferenceCompiler ᗢ Caret Down Link Copy URL External Open LLM text Copy Copy LLM text Share with AI Ask Claude Ask ChatGPT Ask Gemini Ask Copilot Module compiler.coalescing F-String Coalescing for Kida Compiler. RFC: fstring-code-generation Generates Python f-strings for consecutive template output operations instead of multiple buf.append() calls, reducing function call overhead by ~37% in output-heavy templates. Example transformation: Before (5 function calls): _append('<div id="') _append(_e(item["id"])) _append('">') _append(_e(item["name"])) _append('') After (1 function call): _append(f'<div id="{_e(item["id"])}">{_e(item["name"])}') Design: Only coalesce consecutive Data and simple Output nodes Fall back to separate appends for complex expressions (function calls, etc.) Use ast.JoinedStr for f-string generation (handles brace escaping automatically) Detect backslashes in expressions (f-strings don't allow them) Uses inline TYPE_CHECKING declarations for host attributes. See: plan/rfc-mixin-protocol-typing.md 1Class Classes FStringCoalescingMixin 7 ▼ Mixin for f-string coalescing optimization. Host attributes and cross-mixin dependencies are decla… Mixin for f-string coalescing optimization. Host attributes and cross-mixin dependencies are declared via inline TYPE_CHECKING blocks. Methods Internal Methods 7 ▼ _get_pure_filters 0 frozenset[str] ▼ Get combined set of built-in and user-defined pure filters. def _get_pure_filters(self) -> frozenset[str] Returns frozenset[str] _is_coalesceable 1 bool ▼ Check if node can be coalesced into an f-string. Coalesceable nodes: - Dat… def _is_coalesceable(self, node: Any) -> bool Check if node can be coalesced into an f-string. Coalesceable nodes: Data nodes (literal text) Output nodes with simple expressions Non-coalesceable nodes: Control flow (If, For, While, etc.) Output with complex expressions (function calls, etc.) Any node containing backslashes in string constants Parameters Name Type Description node — Returns bool _is_simple_output 1 bool ▼ Check if Output node is simple enough for f-string. def _is_simple_output(self, node: Any) -> bool Parameters Name Type Description node — Returns bool _is_simple_expr 1 bool ▼ Recursively check if expression is simple enough for f-string. Simple expressi… def _is_simple_expr(self, expr: Any) -> bool Recursively check if expression is simple enough for f-string. Simple expressions: Constants (strings, numbers, booleans) Names (variable references) Attribute access (name.attr, name.attr.subattr) Item access (name[key], name["key"]) Pure filters with simple arguments Pipelines with all pure steps InlinedFilter (method calls like .upper()) Complex expressions (NOT coalesceable): Function calls (may have side effects) Ternary expressions (complex control flow) Binary/unary ops (complex evaluation) Expressions containing backslashes Parameters Name Type Description expr — Returns bool _expr_contains_backslash 1 bool ▼ Check if expression would generate code with backslashes. F-strings cannot con… def _expr_contains_backslash(self, expr: Any) -> bool Check if expression would generate code with backslashes. F-strings cannot contain backslashes in expression parts. This is a Python syntax limitation. Parameters Name Type Description expr — Returns bool _compile_coalesced_output 1 ast.stmt ▼ Generate f-string append for coalesced nodes. Note on brace handling: ast.… def _compile_coalesced_output(self, nodes: list[Any]) -> ast.stmt Generate f-string append for coalesced nodes. Note on brace handling: ast.JoinedStr automatically handles brace escaping when the AST is compiled to bytecode. We do NOT manually escape {{ and }}. Literal text goes into ast.Constant nodes as-is. Expressions go into ast.FormattedValue nodes. Note on backslashes: F-strings cannot contain backslashes in expression parts. We detect backslashes during coalesceable checking and fall back. Parameters Name Type Description nodes — Returns ast.stmt _compile_body_with_coalescing 1 list[ast.stmt] ▼ Compile template body with f-string output coalescing. Groups consecutive coal… def _compile_body_with_coalescing(self, nodes: list[Any]) -> list[ast.stmt] Compile template body with f-string output coalescing. Groups consecutive coalesceable nodes and generates single f-string appends for groups of 2+ nodes. Falls back to normal compilation for single nodes or non-coalesceable nodes. Parameters Name Type Description nodes — List of template AST nodes to compile Returns list[ast.stmt] List of Python AST statements ← Previous _protocols Next → compiler List © 2026 Kida built in ᓚᘏᗢ { "linkPreviews": { "enabled": true, "hoverDelay": 200, "hideDelay": 150, "showSection": true, "showReadingTime": true, "showWordCount": true, "showDate": true, "showTags": true, "maxTags": 3, "includeSelectors": [".prose"], "excludeSelectors": ["nav", ".toc", ".breadcrumb", ".pagination", ".card", "[class*='-card']", ".tab-nav", "[class*='-widget']", ".child-items", ".content-tiles"], "allowedHosts": [], "allowedSchemes": ["https"], "hostFailureThreshold": 3 } } window.BENGAL_LAZY_ASSETS = { tabulator: '/kida/assets/js/tabulator.min.js', dataTable: '/kida/assets/js/data-table.js', mermaidToolbar: '/kida/assets/js/mermaid-toolbar.9de5abba.js', mermaidTheme: '/kida/assets/js/mermaid-theme.344822c5.js', graphMinimap: '/kida/assets/js/graph-minimap.ff04e939.js', graphContextual: '/kida/assets/js/graph-contextual.355458ba.js' }; window.BENGAL_ICONS = { close: '/kida/assets/icons/close.911d4fe1.svg', enlarge: '/kida/assets/icons/enlarge.652035e5.svg', copy: '/kida/assets/icons/copy.3d56e945.svg', 'download-svg': '/kida/assets/icons/download.04f07e1b.svg', 'download-png': '/kida/assets/icons/image.c34dfd40.svg', 'zoom-in': '/kida/assets/icons/zoom-in.237b4a83.svg', 'zoom-out': '/kida/assets/icons/zoom-out.38857c77.svg', reset: '/kida/assets/icons/reset.d26dba29.svg' }; Arrow Up -------------------------------------------------------------------------------- Metadata: - Word Count: 1053 - Reading Time: 5 minutes