Source code for srdatalog.ir.hir

'''HIR main orchestrator. Mirrors src/srdatalog/hir/hir.nim.

Entry point: `compile_to_hir(program)` runs the default pipeline
(currently: stratification only; future passes will be appended here as
they are ported from Nim).

A `DIALECT` catalog is also exposed (see `srdatalog.ir.core.dialect`)
so HIR participates in the framework registry alongside `iir.cf`,
`relation.sorted_array`, etc. The HIR types here are not yet
`Op`-subclassed or frozen — that's the next standardization step.
The catalog is purely metadata today.
'''

from __future__ import annotations

from srdatalog.dsl import Program
from srdatalog.ir.core import Dialect
from srdatalog.ir.hir.pass_ import Pipeline
from srdatalog.ir.hir.types import (
  AccessPattern,
  HirProgram,
  HirRuleVariant,
  HirStratum,
  RelationDecl,
  Version,
)

DIALECT = Dialect(
  name='hir',
  types=[
    AccessPattern,
    HirProgram,
    HirRuleVariant,
    HirStratum,
    RelationDecl,
    Version,
  ],
)


# Verifier scaffolding — HIR invariants (stratum dependency acyclicity,
# every relation decl appears in at most one stratum, etc.) land
# incrementally as we encode them.
def _register_passes() -> None:
  from srdatalog.ir.core.passes import verifier

  @verifier(DIALECT)
  def _verify(_prog):
    return []


_register_passes()


[docs] def default_pipeline(verbose: bool = False) -> Pipeline: '''Build the standard HIR pipeline. Nim reference (compileToHir): Pass 0 rewriteConstants [rule-rewrite, ported] Pass 1 rewriteHeadConstants [rule-rewrite, ported] Pass 1.5 optimizeSemiJoins [rule-rewrite, ported] Pass 2 stratify [HIR entry — fixed, built in] Pass 3 generateVariants [HIR transform, ported] Pass 4 planJoins [HIR transform, ported] Pass 5 selectIndices [HIR transform, ported] ''' from srdatalog.ir.hir.index import IndexSelectionPass from srdatalog.ir.hir.plan import JoinPlannerPass from srdatalog.ir.hir.rule_rewrite import ( ConstantRewritePass, HeadConstantRewritePass, SemiJoinPass, WildcardRewritePass, ) from srdatalog.ir.hir.semi_naive import SemiNaiveVariantPass from srdatalog.ir.hir.split import TempIndexRegistrationPass, TempRelSynthesisPass p = Pipeline(verbose=verbose) p.add_rule_rewrite(WildcardRewritePass()) p.add_rule_rewrite(ConstantRewritePass()) p.add_rule_rewrite(HeadConstantRewritePass()) p.add_rule_rewrite(SemiJoinPass()) p.add_hir_transform(SemiNaiveVariantPass()) p.add_hir_transform(JoinPlannerPass()) p.add_hir_transform(TempRelSynthesisPass()) # Pass 4.5 p.add_hir_transform(IndexSelectionPass()) p.add_hir_transform(TempIndexRegistrationPass()) # Pass 5.5 return p
[docs] def compile_to_hir(program: Program, verbose: bool = False) -> HirProgram: '''Run the default HIR pipeline on a Program.''' return default_pipeline(verbose=verbose).compile_to_hir(program)
[docs] def compile_to_mir( program: Program, *, hir: HirProgram | None = None, verbose: bool = False, apply_mir_passes: bool = True, ): '''End-to-end: Program -> HIR -> MIR. Returns a mir_types.Program. By default runs the ported MIR optimization passes (pre_reconstruct_rebuild, clause_order_reorder, prefix_source_reorder). Pass `apply_mir_passes=False` to stop at the raw output of `lower_hir_to_mir_steps`. Pass `hir=...` to reuse an already-computed HirProgram. The default (`hir=None`) runs `compile_to_hir(program, verbose=verbose)` internally. Callers that already have HIR (e.g. `ir.pipeline.compile_program`) should pass it to avoid the redundant pass. ''' import srdatalog.ir.mir.types as mir from srdatalog.ir.hir.lower import lower_hir_to_mir_steps if hir is None: hir = compile_to_hir(program, verbose=verbose) steps = lower_hir_to_mir_steps(hir) if apply_mir_passes: from srdatalog.ir.mir.passes import apply_all_mir_passes steps = apply_all_mir_passes(steps) return mir.Program(steps=[(node, is_rec) for node, is_rec in steps])