Module

compiler.core

Kida Compiler Core — main Compiler class.

The Compiler transforms Kida AST into Python AST, then compiles to executable code objects. Uses a mixin-based design for maintainability.

Design Principles:

  1. AST-to-AST: Generateast.Module, not source strings
  2. StringBuilder: Output viabuf.append(), join at end
  3. Local caching: Cache_escape,_str,buf.appendas locals
  4. O(1) dispatch: Dict-based node type → handler lookup

Performance Optimizations:

  • LOAD_FASTfor cached functions (vsLOAD_GLOBAL+ hash)
  • Method lookup cached once:_append = buf.append
  • Single''.join(buf)at return (vs repeated concatenation)
  • Line markers only for error-prone nodes (Output, For, If, etc.)

Block Inheritance:

Templates with{% extends %}generate:

  1. Block functions:_block_header(ctx, _blocks)

  2. Render function: Registers blocks, delegates to parent

        def _block_header(ctx, _blocks):
            buf = []
            # Block body...
            return ''.join(buf)
    
        def render(ctx, _blocks=None):
            if _blocks is None: _blocks = {}
            _blocks.setdefault('header', _block_header)
            return _extends('base.html', ctx, _blocks)
    

Classes

Compiler 15
Compile Kida AST to Python code objects. The Compiler transforms a Kida Template AST into an `ast.…

Compile Kida AST to Python code objects.

The Compiler transforms a Kida Template AST into anast.Module, then compiles it to a code object ready forexec(). The generated code defines arender(ctx, _blocks=None)function.

Node Dispatch: Uses O(1) dict lookup for node type → handler: python dispatch = { "Data": self._compile_data, "Output": self._compile_output, "If": self._compile_if, ... } handler = dispatch[type(node).__name__]

Line Tracking: For nodes that can cause runtime errors (Output, For, If, etc.), injectsctx['_line'] = Nbefore the node's code. This enables rich error messages with source line numbers.

Attributes

Name Type Description
_env

Parent Environment (for filter/test access)

_name str | None

Template name for error messages

_filename str | None

Source file path for compile()

_locals set[str]

Set of local variable names (loop vars, macro args)

_blocks dict[str, Any]

Dict of block_name → Block node (for inheritance)

_block_counter int

Counter for unique variable names

Methods

compile 3 Any
Compile template AST to code object.
def compile(self, node: TemplateNode, name: str | None = None, filename: str | None = None) -> Any
Parameters
Name Type Description
node

Root Template node

name

Template name for error messages

Default:None
filename

Source filename for error messages

Default:None
Returns
Any Compiled code object ready for exec()
Internal Methods 8
__init__ 1
def __init__(self, env: Environment)
Parameters
Name Type Description
env
_collect_blocks 1
Recursively collect all Block nodes from the AST. This ensures nested blocks (…
def _collect_blocks(self, nodes: Any) -> None

Recursively collect all Block nodes from the AST.

This ensures nested blocks (blocks inside blocks, blocks inside conditionals, etc.) are all registered for compilation.

Parameters
Name Type Description
nodes
_compile_template 1 ast.Module
Generate Python module from template.
def _compile_template(self, node: TemplateNode) -> ast.Module
Parameters
Name Type Description
node
Returns
ast.Module
_make_block_function 2 ast.FunctionDef
Generate a block function: _block_name(ctx, _blocks) -> str.
def _make_block_function(self, name: str, block_node: Any) -> ast.FunctionDef
Parameters
Name Type Description
name
block_node
Returns
ast.FunctionDef
_make_render_function 1 ast.FunctionDef
Generate the render(ctx, _blocks=None) function. Optimization: Cache global fu…
def _make_render_function(self, node: TemplateNode) -> ast.FunctionDef

Generate the render(ctx, _blocks=None) function.

Optimization: Cache global function references as locals for O(1) LOAD_FAST instead of O(1) LOAD_GLOBAL + hash lookup.

For templates with extends:

def render(ctx, _blocks=None):
    if _blocks is None: _blocks = {}
    # Register child blocks
    _blocks.setdefault('name', _block_name)
    # Render parent with blocks
    return _extends('parent.html', ctx, _blocks)
Parameters
Name Type Description
node
Returns
ast.FunctionDef
_make_line_marker 1 ast.stmt
Generate ctx['_line'] = lineno statement for error tracking.
def _make_line_marker(self, lineno: int) -> ast.stmt
Parameters
Name Type Description
lineno
Returns
ast.stmt
_compile_node 1 list[ast.stmt]
Compile a single AST node to Python statements. Complexity: O(1) type dispatch…
def _compile_node(self, node: Any) -> list[ast.stmt]

Compile a single AST node to Python statements.

Complexity: O(1) type dispatch using class name lookup.

For nodes that can cause runtime errors, injects a line marker statement (ctx['_line'] = N) before the node's code. This enables rich error messages with source line numbers.

Parameters
Name Type Description
node
Returns
list[ast.stmt]
_get_node_dispatch 0 dict[str, Callable]
Get node type dispatch table (cached on first call).
def _get_node_dispatch(self) -> dict[str, Callable]
Returns
dict[str, Callable]