Classes
ControlFlowMixin
9
▼
Mixin for compiling control flow statements.
Host attributes and cross-mixin dependencies are decl…
ControlFlowMixin
9
▼
Mixin for compiling control flow statements.
Host attributes and cross-mixin dependencies are declared via inline TYPE_CHECKING blocks.
Methods
Internal Methods 9 ▼
_wrap_with_scope
2
list[ast.stmt]
▼
Wrap statements with scope push/pop for block-scoped variables.
When source_no…
_wrap_with_scope
2
list[ast.stmt]
▼
def _wrap_with_scope(self, body_stmts: list[ast.stmt], source_nodes: Any = None) -> list[ast.stmt]
Wrap statements with scope push/pop for block-scoped variables.
When source_nodes is provided and contains no Set, Let, Capture, or Export nodes, the scope push/pop is skipped entirely — avoiding unnecessary dict allocation and list append/pop per block entry.
Generates (when scoping is needed): _scope_stack.append({}) ... body statements ... _scope_stack.pop()
Parameters
| Name | Type | Description |
|---|---|---|
body_stmts |
— |
|
source_nodes |
— |
Default:None
|
Returns
list[ast.stmt]
_compile_break
1
list[ast.stmt]
▼
Compile {% break %} loop control.
Part of RFC: kida-modern-syntax-features.
_compile_break
1
list[ast.stmt]
▼
def _compile_break(self, node: Node) -> list[ast.stmt]
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
list[ast.stmt]
_compile_continue
1
list[ast.stmt]
▼
Compile {% continue %} loop control.
Part of RFC: kida-modern-syntax-features.
_compile_continue
1
list[ast.stmt]
▼
def _compile_continue(self, node: Node) -> list[ast.stmt]
Compile {% continue %} loop control.
Part of RFC: kida-modern-syntax-features.
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
list[ast.stmt]
_compile_while
1
list[ast.stmt]
▼
Compile {% while cond %}...{% end %} loop.
**Generates:**
while condition:
…
_compile_while
1
list[ast.stmt]
▼
def _compile_while(self, node: While) -> list[ast.stmt]
Compile {% while cond %}...{% end %} loop.
Generates: while condition: ... body ...
Part of RFC: kida-2.0-moonshot (While Loops).
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
list[ast.stmt]
_compile_if
1
list[ast.stmt]
▼
Compile {% if %} conditional.
_compile_if
1
list[ast.stmt]
▼
def _compile_if(self, node: If) -> list[ast.stmt]
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
list[ast.stmt]
_uses_loop_variable
1
bool
▼
Check if any node in the tree references the 'loop' variable.
This enables laz…
_uses_loop_variable
1
bool
▼
def _uses_loop_variable(self, nodes: Any) -> bool
Check if any node in the tree references the 'loop' variable.
This enables lazy LoopContext optimization: when loop.index, loop.first, etc. are not used, we can skip creating the LoopContext wrapper and iterate directly over the items (1.80x faster per benchmark).
Parameters
| Name | Type | Description |
|---|---|---|
nodes |
— |
A node or sequence of nodes to check |
Returns
bool
True if 'loop' is referenced anywhere in the tree
_compile_for
1
list[ast.stmt]
▼
Compile {% for %} loop with optional LoopContext.
Generates one of three forms…
_compile_for
1
list[ast.stmt]
▼
def _compile_for(self, node: For) -> list[ast.stmt]
Compile {% for %} loop with optional LoopContext.
Generates one of three forms based on loop.* usage and {% empty %} presence:
When loop.* IS used (requires materialized list): _iter_source = iterable _loop_items = list(_iter_source) if _iter_source is not None else [] if _loop_items: loop = _LoopContext(_loop_items) for item in loop: ... body ... else: ... empty block ...
When loop.* is NOT used and has {% empty %} (sentinel pattern): _iter_source = iterable _had_items = False if _iter_source is not None: for item in _iter_source: _had_items = True ... body ... if not _had_items: ... empty block ...
When loop.* is NOT used and no {% empty %} (direct iteration): _iter_source = iterable if _iter_source is not None: for item in _iter_source: ... body ...
Optimization: Loop variables are tracked as locals and accessed directly (O(1) LOAD_FAST) instead of through ctx dict lookup.
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
list[ast.stmt]
_compile_async_for
1
list[ast.stmt]
▼
Compile {% async for %} loop with AsyncLoopContext.
Unlike sync _compile_for()…
_compile_async_for
1
list[ast.stmt]
▼
def _compile_async_for(self, node: AsyncFor) -> list[ast.stmt]
Compile {% async for %} loop with AsyncLoopContext.
Unlike sync _compile_for(), this does NOT call list() on the iterable. Instead it generates ast.AsyncFor for native async iteration and uses a boolean flag for {% empty %} detection.
When compiling for sync functions (_async_mode=False), emits a pass placeholder. The Template-level guard prevents sync rendering of async templates, so this code path is unreachable at runtime.
Generates (async mode): _had_items_N = False loop = _AsyncLoopContext() # if loop.* used async for item in iterable: _had_items_N = True loop.advance(item) # if loop.* used ... body ... if not _had_items_N: ... empty block ...
Part of RFC: rfc-async-rendering.
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
list[ast.stmt]
_extract_names
1
list[str]
▼
Extract variable names from a target expression.
_extract_names
1
list[str]
▼
def _extract_names(self, node: Node) -> list[str]
Parameters
| Name | Type | Description |
|---|---|---|
node |
— |
Returns
list[str]