Source code for srdatalog.ir.dialects.relation.d2l.ops
'''relation.d2l ops — Device2LevelIndex segment-aware nodes.
D2L FULL_VER reads expose two view slots (HEAD + FULL); operators that
consume them have to visit both segments. The legacy emitter does this
with a `for (_seg = 0; _seg < view_count; ...)` loop wrapping the join
body, reassigning the view variable per iteration. `D2lSegmentLoop`
captures that pattern as a first-class IIR op.
See also `relation.d2l.__init__.view_count` for the per-source slot
arithmetic.
'''
from __future__ import annotations
from dataclasses import dataclass
from typing import final
from srdatalog.ir.core import Op
[docs]
@final
@dataclass(frozen=True, slots=True)
class D2lSegmentLoop(Op):
'''Iterate over a D2L source's segments (HEAD then FULL).
Two emit shapes:
Single-line (multi-source nested CJ — legacy
`_nested_column_join_multi`): when `local_view_var == ''`, lowers to
for (int <seg_var> = 0; <seg_var> < <view_count>; <seg_var>++) {
[auto ]<view_var> = views[<base_slot> + <seg_var>];
<body>
}
`declare=False` rebinds the kernel-start `view_var`; `declare=True`
declares a fresh per-segment view (single-source nested CJ case,
N5.3).
Two-line (root CJ multi non-first source — legacy `_root_cj_multi`
phase 2): when `local_view_var` is non-empty, lowers to
for (int <seg_var> = 0; <seg_var> < <view_count>; <seg_var>++) {
auto <local_view_var> = views[<base_slot> + <seg_var>];
<view_var> = <local_view_var>;
<body>
}
The local var is the SHORT name (`view_<rel>_<src_idx>`) the
immediately-following prefix narrowing references; the fixed
canonical kernel-start view is rebound so downstream code that
uses the LONG name also sees the current segment's array. The
assignment line is omitted when `local_view_var == view_var`
(matches legacy `if fixed_view_var != view_var` guard).
Indent semantics (both shapes): the wrapped `body` emits at one
level deeper than the segment loop's `for` preamble, but
`EmitCtx.segment_depth` is bumped so any inner `IntersectIter`
anchors its body lines / body op back to the *outer* indent —
matching the legacy `seg_indent`-vs-`ind(ctx)` indent quirk.
'''
seg_var: str
view_var: str
base_slot: int
view_count: int
declare: bool
local_view_var: str
body: Op
__all__ = ['D2lSegmentLoop']