# expressions URL: /api/compiler/expressions/ Section: compiler -------------------------------------------------------------------------------- expressions - 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.expressions Expression compilation for Kida compiler. Provides mixin for compiling Kida expression AST nodes to Python AST expressions. Uses inline TYPE_CHECKING declarations for host attributes. See: plan/rfc-mixin-protocol-typing.md 1Class Classes ExpressionCompilationMixin 11 ▼ Mixin for compiling expressions. Host attributes and cross-mixin dependencies are declared via inl… Mixin for compiling expressions. Host attributes and cross-mixin dependencies are declared via inline TYPE_CHECKING blocks. Methods Internal Methods 11 ▼ _get_filter_suggestion 1 str | None ▼ Find closest matching filter name for typo suggestions. Uses difflib.get_close… def _get_filter_suggestion(self, name: str) -> str | None Find closest matching filter name for typo suggestions. Uses difflib.get_close_matches with 0.6 cutoff for reasonable typo detection. Returns None if no close match found. Parameters Name Type Description name — Returns str | None _get_test_suggestion 1 str | None ▼ Find closest matching test name for typo suggestions. Uses difflib.get_close_m… def _get_test_suggestion(self, name: str) -> str | None Find closest matching test name for typo suggestions. Uses difflib.get_close_matches with 0.6 cutoff for reasonable typo detection. Returns None if no close match found. Parameters Name Type Description name — Returns str | None _is_potentially_string 1 bool ▼ Check if node could produce a string value (macro call, filter chain). Used to… def _is_potentially_string(self, node: Any) -> bool Check if node could produce a string value (macro call, filter chain). Used to determine when numeric coercion is needed for arithmetic operations. Recursively checks nested expressions to catch Filter nodes inside parentheses. This handles cases like (a | length) + (b | length) where the left/right operands are Filter nodes that need numeric coercion. Parameters Name Type Description node — Returns bool _wrap_coerce_numeric 1 ast.expr ▼ Wrap expression in _coerce_numeric() call for arithmetic safety. Ensures that … def _wrap_coerce_numeric(self, expr: ast.expr) -> ast.expr Wrap expression in _coerce_numeric() call for arithmetic safety. Ensures that Markup objects (from macros) are converted to numbers before arithmetic operations, preventing string multiplication. Parameters Name Type Description expr — Returns ast.expr _compile_expr 2 ast.expr ▼ Compile expression node to Python AST expression. Complexity: O(1) dispatch + … def _compile_expr(self, node: Any, store: bool = False) -> ast.expr Compile expression node to Python AST expression. Complexity: O(1) dispatch + O(d) for recursive expressions. Parameters Name Type Description node — store — Default: False Returns ast.expr _compile_null_coalesce 1 ast.expr ▼ Compile a ?? b to handle both None and undefined variables. Uses _null_coalesc… def _compile_null_coalesce(self, node: Any) -> ast.expr Compile a ?? b to handle both None and undefined variables. Uses _null_coalesce helper to catch UndefinedError for undefined variables. Part of RFC: kida-modern-syntax-features. The helper is called as: _null_coalesce(lambda: a, lambda: b) This allows: a ?? b to return b if a is undefined (UndefinedError) a ?? b to return b if a is None a ?? b to return a if a is any other value (including falsy: 0, '', []) Parameters Name Type Description node — Returns ast.expr _compile_optional_getattr 1 ast.expr ▼ Compile obj?.attr using walrus operator to avoid double evaluation. obj?.attr … def _compile_optional_getattr(self, node: Any) -> ast.expr Compile obj?.attr using walrus operator to avoid double evaluation. obj?.attr compiles to: '' if (_oc := obj) is None else (_oc_val := _getattr_none(_oc, 'attr')) if _oc_val is not None else '' The double check ensures that: If obj is None, return '' If obj.attr is None, return '' (for output) but preserve None for ?? For null coalescing to work, we need a different approach: the optional chain preserves None so ?? can check it, but for direct output, None becomes ''. Actually, we return None but rely on the caller to handle None → '' conversion. For output, the expression is wrapped differently. Simplified: Return None when short-circuiting, let output handle conversion. Part of RFC: kida-modern-syntax-features. Parameters Name Type Description node — Returns ast.expr _compile_optional_getitem 1 ast.expr ▼ Compile obj?[key] using walrus operator to avoid double evaluation. obj?[key] … def _compile_optional_getitem(self, node: Any) -> ast.expr Compile obj?[key] using walrus operator to avoid double evaluation. obj?[key] compiles to: None if (_oc := obj) is None else _oc[key] Part of RFC: kida-modern-syntax-features. Parameters Name Type Description node — Returns ast.expr _compile_range 1 ast.expr ▼ Compile range literal to range() call. 1..10 → range(1, 11) # inclusiv… def _compile_range(self, node: Any) -> ast.expr Compile range literal to range() call. 1..10 → range(1, 11) # inclusive 1...11 → range(1, 11) # exclusive 1..10 by 2 → range(1, 11, 2) Part of RFC: kida-modern-syntax-features. Parameters Name Type Description node — Returns ast.expr _compile_inlined_filter 1 ast.Call ▼ Compile inlined filter to direct method call. Generates: _str(value).method(*a… def _compile_inlined_filter(self, node: Any) -> ast.Call Compile inlined filter to direct method call. Generates: _str(value).method(*args) This replaces filter dispatch overhead with a direct method call, providing ~5-10% speedup for filter-heavy templates. Parameters Name Type Description node — Returns ast.Call _compile_pipeline 1 ast.expr ▼ Compile pipeline: expr |> filter1 |> filter2. Pipelines compile to nested filt… def _compile_pipeline(self, node: Any) -> ast.expr Compile pipeline: expr |> filter1 |> filter2. Pipelines compile to nested filter calls using the _filters dict, exactly like regular filter chains. The difference is purely syntactic. expr |> a |> b(x) → _filters['b'](_filters'a', x) Validates filter existence at compile time (same as Filter nodes). Parameters Name Type Description node — Returns ast.expr ← Previous core Next → utils 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: 1362 - Reading Time: 7 minutes