vyre-libs 0.6.3

vyre Category A library ecosystem - pure-IR compositions over vyre-ops hardware primitives
Documentation
use std::path::Path;

use super::PreprocessRun;
use crate::parsing::c::preprocess::gpu_pipeline::conditional_events::push_conditional_event;
use crate::parsing::c::preprocess::gpu_pipeline::conditional_stack::ConditionalFrame;
use crate::parsing::c::preprocess::gpu_pipeline::live_state::{
    cached_live_macro_name_buffers, recompute_if_expr_truth_gpu_with_scratch,
    recompute_ifdef_truth_gpu_with_scratch, LiveMacroNameBuffers,
};
use crate::parsing::c::preprocess::gpu_pipeline::source_spans::token_row_bytes;
use crate::parsing::c::preprocess::gpu_pipeline::{
    ClassifiedTokens, ConditionalEventKind, ConditionalEventResidency,
};

pub(super) fn conditionals_active(conditionals: &[ConditionalFrame]) -> bool {
    conditionals
        .last()
        .map(|frame| frame.current_active)
        .unwrap_or(true)
}

pub(super) fn apply_ifdef(
    run: &mut PreprocessRun<'_>,
    file_path: &Path,
    classified: &ClassifiedTokens,
    conditionals: &mut Vec<ConditionalFrame>,
    live_macro_buffers_cache: &mut Option<LiveMacroNameBuffers>,
    directive_row: usize,
    directive_byte_offset: usize,
    negated: bool,
    guard_name: Option<&[u8]>,
    precomputed_truth: Option<bool>,
    gpu_ifdef: &mut u32,
) -> Result<(), String> {
    let parent = conditionals_active(conditionals);
    let depth_before = conditionals.len();
    let (truth, state_residency) = if !parent {
        (false, ConditionalEventResidency::GpuResidentTruth)
    } else if let Some(truth) = precomputed_truth {
        (truth, ConditionalEventResidency::GpuResidentTruth)
    } else if negated {
        if let Some(guard_name) = guard_name {
            (
                !run.macro_index.contains_key(guard_name),
                ConditionalEventResidency::HostLiveMacroTable,
            )
        } else {
            let row_bytes = token_row_bytes(classified, directive_row)?;
            *gpu_ifdef += 1;
            let live_macro_buffers =
                cached_live_macro_name_buffers(&run.macros, live_macro_buffers_cache)?;
            (
                recompute_ifdef_truth_gpu_with_scratch(
                    run.dispatcher,
                    row_bytes,
                    classified.directive_kinds[directive_row],
                    negated,
                    live_macro_buffers,
                    &mut run.live_conditional_scratch,
                )?,
                ConditionalEventResidency::GpuResidentTruth,
            )
        }
    } else {
        let row_bytes = token_row_bytes(classified, directive_row)?;
        *gpu_ifdef += 1;
        let live_macro_buffers =
            cached_live_macro_name_buffers(&run.macros, live_macro_buffers_cache)?;
        (
            recompute_ifdef_truth_gpu_with_scratch(
                run.dispatcher,
                row_bytes,
                classified.directive_kinds[directive_row],
                negated,
                live_macro_buffers,
                &mut run.live_conditional_scratch,
            )?,
            ConditionalEventResidency::GpuResidentTruth,
        )
    };
    conditionals.push(ConditionalFrame {
        parent_active: parent,
        branch_taken: truth,
        current_active: parent && truth,
        saw_else: false,
    });
    push_conditional_event(
        &mut run.conditional_events,
        file_path,
        if negated {
            ConditionalEventKind::Ifndef
        } else {
            ConditionalEventKind::Ifdef
        },
        directive_row,
        directive_byte_offset,
        depth_before,
        conditionals.len(),
        parent,
        Some(truth),
        parent && truth,
        truth,
        state_residency,
    )
}

pub(super) fn apply_ifexpr(
    run: &mut PreprocessRun<'_>,
    file_path: &Path,
    classified: &ClassifiedTokens,
    conditionals: &mut Vec<ConditionalFrame>,
    live_macro_buffers_cache: &mut Option<LiveMacroNameBuffers>,
    directive_row: usize,
    directive_byte_offset: usize,
    is_elif: bool,
    gpu_if: &mut u32,
) -> Result<(), String> {
    if is_elif {
        apply_elif(
            run,
            file_path,
            classified,
            conditionals,
            live_macro_buffers_cache,
            directive_row,
            directive_byte_offset,
            gpu_if,
        )
    } else {
        apply_if(
            run,
            file_path,
            classified,
            conditionals,
            live_macro_buffers_cache,
            directive_row,
            directive_byte_offset,
            gpu_if,
        )
    }
}

pub(super) fn apply_else(
    run: &mut PreprocessRun<'_>,
    file_path: &Path,
    conditionals: &mut [ConditionalFrame],
    directive_row: usize,
    directive_byte_offset: usize,
) -> Result<(), String> {
    let depth_before = conditionals.len();
    let Some(frame) = conditionals.last_mut() else {
        return Err(format!(
            "vyre-libs::gpu_pipeline: #else without matching #if in {}. Fix: repair conditional directive structure.",
            file_path.display()
        ));
    };
    if frame.saw_else {
        return Err(format!(
            "vyre-libs::gpu_pipeline: duplicate #else in {}. Fix: keep exactly one #else per #if block.",
            file_path.display()
        ));
    }
    let take = !frame.branch_taken;
    frame.current_active = frame.parent_active && take;
    frame.branch_taken = true;
    frame.saw_else = true;
    let parent_active = frame.parent_active;
    let current_active = frame.current_active;
    let branch_taken = frame.branch_taken;
    push_conditional_event(
        &mut run.conditional_events,
        file_path,
        ConditionalEventKind::Else,
        directive_row,
        directive_byte_offset,
        depth_before,
        depth_before,
        parent_active,
        None,
        current_active,
        branch_taken,
        ConditionalEventResidency::HostStackThreading,
    )
}

pub(super) fn apply_endif(
    run: &mut PreprocessRun<'_>,
    file_path: &Path,
    conditionals: &mut Vec<ConditionalFrame>,
    directive_row: usize,
    directive_byte_offset: usize,
) -> Result<(), String> {
    let depth_before = conditionals.len();
    if conditionals.pop().is_none() {
        return Err(format!(
            "vyre-libs::gpu_pipeline: #endif without matching #if in {}. Fix: repair conditional directive structure.",
            file_path.display()
        ));
    }
    let current_active = conditionals_active(conditionals);
    push_conditional_event(
        &mut run.conditional_events,
        file_path,
        ConditionalEventKind::Endif,
        directive_row,
        directive_byte_offset,
        depth_before,
        conditionals.len(),
        current_active,
        None,
        current_active,
        conditionals
            .last()
            .map(|frame| frame.branch_taken)
            .unwrap_or(false),
        ConditionalEventResidency::HostStackThreading,
    )
}

fn apply_elif(
    run: &mut PreprocessRun<'_>,
    file_path: &Path,
    classified: &ClassifiedTokens,
    conditionals: &mut [ConditionalFrame],
    live_macro_buffers_cache: &mut Option<LiveMacroNameBuffers>,
    directive_row: usize,
    directive_byte_offset: usize,
    gpu_if: &mut u32,
) -> Result<(), String> {
    let depth_before = conditionals.len();
    let Some(frame) = conditionals.last_mut() else {
        return Err(format!(
            "vyre-libs::gpu_pipeline: #elif without matching #if in {}. Fix: repair conditional directive structure.",
            file_path.display()
        ));
    };
    if frame.saw_else {
        return Err(format!(
            "vyre-libs::gpu_pipeline: #elif after #else in {}. Fix: place all #elif branches before #else.",
            file_path.display()
        ));
    }
    let should_evaluate = frame.parent_active && !frame.branch_taken;
    let truth = if !should_evaluate {
        false
    } else {
        let row_bytes = token_row_bytes(classified, directive_row)?;
        *gpu_if += 1;
        let live_macro_buffers =
            cached_live_macro_name_buffers(&run.macros, live_macro_buffers_cache)?;
        recompute_if_expr_truth_gpu_with_scratch(
            run.dispatcher,
            row_bytes,
            classified.directive_kinds[directive_row],
            &run.macros,
            live_macro_buffers,
            &mut run.live_conditional_scratch,
        )?
    };
    let take = should_evaluate && truth;
    frame.current_active = frame.parent_active && take;
    frame.branch_taken |= take;
    let parent_active = frame.parent_active;
    let current_active = frame.current_active;
    let branch_taken = frame.branch_taken;
    push_conditional_event(
        &mut run.conditional_events,
        file_path,
        ConditionalEventKind::Elif,
        directive_row,
        directive_byte_offset,
        depth_before,
        depth_before,
        parent_active,
        Some(truth),
        current_active,
        branch_taken,
        ConditionalEventResidency::GpuResidentTruth,
    )
}

fn apply_if(
    run: &mut PreprocessRun<'_>,
    file_path: &Path,
    classified: &ClassifiedTokens,
    conditionals: &mut Vec<ConditionalFrame>,
    live_macro_buffers_cache: &mut Option<LiveMacroNameBuffers>,
    directive_row: usize,
    directive_byte_offset: usize,
    gpu_if: &mut u32,
) -> Result<(), String> {
    let parent = conditionals_active(conditionals);
    let depth_before = conditionals.len();
    let truth = if !parent {
        false
    } else {
        let row_bytes = token_row_bytes(classified, directive_row)?;
        *gpu_if += 1;
        let live_macro_buffers =
            cached_live_macro_name_buffers(&run.macros, live_macro_buffers_cache)?;
        recompute_if_expr_truth_gpu_with_scratch(
            run.dispatcher,
            row_bytes,
            classified.directive_kinds[directive_row],
            &run.macros,
            live_macro_buffers,
            &mut run.live_conditional_scratch,
        )?
    };
    conditionals.push(ConditionalFrame {
        parent_active: parent,
        branch_taken: truth,
        current_active: parent && truth,
        saw_else: false,
    });
    push_conditional_event(
        &mut run.conditional_events,
        file_path,
        ConditionalEventKind::If,
        directive_row,
        directive_byte_offset,
        depth_before,
        conditionals.len(),
        parent,
        Some(truth),
        parent && truth,
        truth,
        ConditionalEventResidency::GpuResidentTruth,
    )
}