//! Redline: Compile-time performance guarantees for Rust.
//!
//! Annotate a function with a latency or throughput bound.
//! The compiler analyzes every code path, every allocation, every syscall.
//! If any path can exceed the bound, it won't compile.
//!
//! ```ignore
//! #[redline(latency = "< 1ms")]
//! fn process_request(req: &Request) -> Response {
//!     // compiler enforces: every path < 1ms
//! }
//!
//! #[redline(throughput = "> 1GB/s")]
//! fn encode_batch(data: &[u8]) -> Vec<u8> {
//!     // compiler enforces: sustained throughput > 1GB/s
//! }
//!
//! #[redline(allocs = 0)]
//! fn hot_path(data: &[u8]) -> u64 {
//!     // compiler enforces: zero heap allocations
//! }
//! ```

extern crate proc_macro;

mod analyze;
mod cost;
mod parse;

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

use crate::analyze::analyze_function;
use crate::parse::RedlineAttr;

/// The `#[redline(...)]` attribute macro.
///
/// Supported constraints:
/// - `latency = "< 1ms"` / `latency = "< 100us"` / `latency = "< 5ns"`
/// - `throughput = "> 1GB/s"` / `throughput = "> 500MB/s"`
/// - `allocs = 0` / `allocs = "< 5"`
/// - `syscalls = 0`
/// - `max_stack = "< 4KB"`
#[proc_macro_attribute]
pub fn redline(attr: TokenStream, item: TokenStream) -> TokenStream {
    let attr = parse_macro_input!(attr as RedlineAttr);
    let func = parse_macro_input!(item as ItemFn);

    match analyze_function(&attr, &func) {
        Ok(()) => {
            // All constraints satisfied, emit the function unchanged
            let output = quote! { #func };
            output.into()
        }
        Err(violations) => {
            // Emit compile errors for each violation
            let errors: Vec<_> = violations
                .iter()
                .map(|v| {
                    let msg = format!("redline: {}", v);
                    quote! { compile_error!(#msg); }
                })
                .collect();

            let output = quote! {
                #(#errors)*
                #func
            };
            output.into()
        }
    }
}
