/**
 * Shell AST types for compound command parsing.
 *
 * Represents the structural tree of a compound shell command after parsing.
 * The tree preserves operator relationships between segments so that per-segment
 * policy evaluation has full structural context.
 *
 * Node hierarchy:
 *   ShellNode = CommandNode | PipeNode | SequenceNode | SubshellNode
 *
 * @module normalization/ast
 */
// ── AST utilities ──────────────────────────────────────────────────────────────
/**
 * Collects all CommandNode leaves from a ShellNode tree in left-to-right order.
 *
 * @param node - The root node to traverse.
 * @returns Ordered list of CommandNode leaves.
 */
export function collectCommandNodes(node, acc = []) {
    switch (node.kind) {
        case 'command':
            acc.push(node);
            return acc;
        case 'pipe':
            collectCommandNodes(node.left, acc);
            collectCommandNodes(node.right, acc);
            return acc;
        case 'sequence':
            collectCommandNodes(node.left, acc);
            collectCommandNodes(node.right, acc);
            return acc;
        case 'subshell':
            if (node.inner)
                collectCommandNodes(node.inner, acc);
            return acc;
    }
}
/**
 * Returns the operator chain connecting a node to its siblings, for display
 * in denial messages.
 *
 * @param node - The node to describe.
 * @returns A human-readable description of the node kind.
 */
export function describeNode(node) {
    switch (node.kind) {
        case 'command': return `command(${node.command})`;
        case 'pipe': return `pipe(${describeNode(node.left)} | ${describeNode(node.right)})`;
        case 'sequence': return `sequence(${describeNode(node.left)} ${node.operator} ${describeNode(node.right)})`;
        case 'subshell': return `subshell(${node.raw})`;
    }
}
