from ..metamodel.compiler import Pass
from ..metamodel.typer import Checker, InferTypes

from ..metamodel.rewrite import (
    DNFUnionSplitter, FormatOutputs, HandleAggregationsAndRanks
)
from .rewrite import (
    AlgorithmPass, AnnotateConstraints, CDC, ConstantsToVars, DeduplicateVars,
    ExtractCommon, EliminateData, ExtractKeys, Flatten, FlattenScript,
    FunctionAnnotations, PeriodMath, QuantifyVars, Splinter, SplitMultiCheckRequires,
    UnifyDefinitions,
)

def lqp_passes() -> list[Pass]:
    return [
        SplitMultiCheckRequires(),
        FunctionAnnotations(),
        AnnotateConstraints(),
        Checker(),
        CDC(), # specialize to physical relations before extracting nested and typing
        InferTypes(),
        DNFUnionSplitter(), # Handle unions that require DNF decomposition
        ExtractKeys(), # Create a logical for each valid combinations of keys
        FormatOutputs(),
        ExtractCommon(), # Extracts tasks that will become common after Flatten into their own definition
        Flatten(), # Move nested tasks to the top level, and various related things touched along the way
        FlattenScript(), # Additional flattening specific to scripts
        HandleAggregationsAndRanks(), # Handle aggregation and rank dependencies
        Splinter(), # Splits multi-headed rules into multiple rules
        QuantifyVars(), # Adds missing existentials
        EliminateData(),  # Turns Data nodes into ordinary relations.
        DeduplicateVars(),  # Deduplicates vars in Updates and Outputs.
        ConstantsToVars(),  # Turns constants in Updates and Outputs into vars.
        AlgorithmPass(),
        PeriodMath(),  # Rewrite date period uses.
        UnifyDefinitions(), # Unify relations with multiple definitions.
    ]
