//! glslt is the main library that supports the GLSL Template compiler transforms. If you are
//! building a system that relies on transforming GLSLT code, you'll want to interact with this
//! library directly instead of the command-line interface provided by `glsltc`.
//!
//! # Usage
//!
//! ## Rust crate
//!
//! The glslt crate manipulates syntax trees generated by the [glsl-lang
//! crate](https://github.com/alixinne/glsl-lang).
//!
//! ```rust
//! use glslt::glsl_lang::{ast::*, parse::IntoParseBuilderExt};
//! use glslt::transform::{Unit, TransformUnit};
//!
//! let glsl_src = r#"
//! float sdf3d(in vec3 p);
//! float colort();
//!
//! float sdSphere(vec3 p, float r) {
//!     return length(p) - r;
//! }
//!
//! float opElongate(in sdf3d primitive, in colort C, in vec3 p, in colort D, in vec3 h) {
//!     vec3 q = p - clamp(p, -h, h);
//!     return C() * primitive(q) * D();
//! }
//!
//! void mainImage(out vec4 fragColor, in vec2 fragCoord) {
//!     float sz = 5.;
//!     fragColor = vec4(vec3(opElongate(sdSphere(_p, sz), 1.0, vec3(fragCoord, 0.), 2.0, vec3(1., 2., 3.))), 1.0);
//! }
//! "#;
//!
//! // Parse the GLSLT source code
//! let tu: TranslationUnit = glsl_src
//!     .builder()
//!     .context(&glslt::parse::make_parse_context(None))
//!     .parse()
//!     .expect("failed to parse GLSLT source")
//!     .0;
//!
//! // Create the transform unit
//! let mut unit = Unit::new();
//!
//! // Parse declarations
//! for decl in tu.0.into_iter() {
//!     unit.parse_external_declaration(decl).expect("failed to parse declaration");
//! }
//!
//! // Generate the result
//! let tu = unit.into_translation_unit().expect("failed to generate output");
//!
//! // Transpile the syntax tree to GLSL source
//! let mut output_src = String::new();
//! glsl_lang::transpiler::glsl::show_translation_unit(
//!     &mut output_src,
//!     &tu,
//!     glsl_lang::transpiler::glsl::FormattingState::default(),
//! ).expect("failed to generate GLSL");
//! ```
//!
//! ## Python library
//!
//! If you installed the glslt library via `pip install glslt` or `maturin
//! develop`, you may use the Python interface to the GLSLT compiler.
//!
//! ```python
//! import glslt
//!
//! # Parse the `sdf.glsl` file with `my-glsl-lib/include` being a system include
//! # directory for #include resolution
//! translation_unit = glslt.parse_files(["sdf.glsl"], ["my-glsl-lib/include"])
//!
//! # Create a new minimizing transform unit
//! unit = glslt.MinUnit()
//!
//! # Add the parsed declarations to the transform unit
//! unit.add_unit(translation_unit)
//!
//! # Get the output of the transform
//! result = unit.to_translation_unit(["mainImage"])
//!
//! # Print the GLSL code
//! print(result.to_glsl())
//! ```

#![deny(missing_docs)]

#[macro_use]
extern crate log;

pub use glsl_lang;

/// Prefix for generated names for functions and captured parameters
pub const DEFAULT_PREFIX: &str = "_glslt_";

/// Global trasnform parameters
#[derive(Debug, Clone)]
pub struct TransformConfig {
    /// Identifier prefix for code generation
    pub prefix: String,
}

impl Default for TransformConfig {
    fn default() -> Self {
        Self {
            prefix: DEFAULT_PREFIX.to_owned(),
        }
    }
}

/// Builder for [`TransformConfig`](struct.TransformConfig.html).
#[derive(Default, Debug, Clone)]
pub struct TransformConfigBuilder {
    /// Identifier prefix for code generation
    prefix: Option<String>,
}

impl TransformConfigBuilder {
    /// Identifier prefix for code generation
    #[allow(unused_mut)]
    pub fn prefix(&mut self, value: String) -> &mut Self {
        let mut new = self;
        new.prefix = Some(value);
        new
    }

    ///Builds a new `TransformConfig`.
    ///
    ///# Errors
    ///
    ///If a required field has not been initialized.
    pub fn build(self) -> TransformConfig {
        TransformConfig {
            prefix: match self.prefix {
                Some(value) => value,
                None => DEFAULT_PREFIX.to_owned(),
            },
        }
    }
}

pub mod api;

mod error;
pub use error::*;

pub mod glsl_ext;

#[cfg(feature = "parse")]
pub mod parse;

pub mod transform;
pub use transform::{transform, transform_min};

pub mod util;
