aeri 0.3.0

Aeri is a Cardano smart contract language by Knott Dynamics, created by Trevor Knott, with its official compiler and CLI.
Documentation
//! Backend target constants and helper methods for emission selection.
//!
//! The `Target` enum and constants here drive blueprint metadata, output file
//! naming, and deployability flags.

use crate::{diagnostic::Result, ir::Program};

/// Textual IR compiler identifier used by preview artifacts.
pub const PREVIEW_COMPILER_TARGET: &str = "aeri-text-ir";
/// Preview builds are not directly deployable to Cardano.
pub const PREVIEW_CARDANO_DEPLOYABLE: bool = false;
/// Default blueprint filename for preview builds.
pub const PREVIEW_BLUEPRINT_FILE: &str = "blueprint.preview.json";
/// Default extension for rendered preview IR files.
pub const PREVIEW_SCRIPT_EXTENSION: &str = "aeri.ir";
/// UPLC/CBOR compiler identifier used in deployable blueprints.
pub const UPLC_COMPILER_TARGET: &str = "cardano-uplc-cbor";
/// UPLC builds are deployable when successfully emitted.
pub const UPLC_CARDANO_DEPLOYABLE: bool = true;
/// Default blueprint filename for UPLC builds.
pub const UPLC_BLUEPRINT_FILE: &str = "blueprint.uplc.json";
/// Default blueprint filename for Plutus V3 builds.
pub const UPLC_V3_BLUEPRINT_FILE: &str = "blueprint.uplc-v3.json";
/// Default extension for emitted UPLC script JSON files.
pub const UPLC_SCRIPT_EXTENSION: &str = "plutus.json";
/// Plutus version string used in deployed blueprints.
pub const UPLC_PLUTUS_VERSION: &str = "PlutusV2";

/// Ledger calling convention, context layout, and script hash domain.
/// Both versions use the compiler's supported UPLC 1.0.0 core subset.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PlutusVersion {
    V2,
    V3,
}

impl PlutusVersion {
    /// Language discriminator used in Cardano script hashes and text envelopes.
    pub fn script_version(self) -> u8 {
        match self {
            Self::V2 => 2,
            Self::V3 => 3,
        }
    }

    /// Version label used in blueprint metadata.
    pub fn blueprint_name(self) -> &'static str {
        match self {
            Self::V2 => UPLC_PLUTUS_VERSION,
            Self::V3 => "PlutusV3",
        }
    }

    pub(crate) fn context_fields(self) -> usize {
        match self {
            Self::V2 => 2,
            Self::V3 => 3,
        }
    }

    pub(crate) fn tx_info_fields(self) -> usize {
        match self {
            Self::V2 => 12,
            Self::V3 => 16,
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Emission target for compile and inspection operations.
pub enum Target {
    /// Human-readable preview target: text IR and non-deployable metadata.
    Preview,
    /// Constrained, deployable Plutus V2 emission target.
    Uplc,
    /// Constrained, deployable Plutus V3 emission target.
    UplcV3,
}

impl Target {
    /// Returns the CLI/config key for this target.
    pub fn name(self) -> &'static str {
        match self {
            Self::Preview => "preview",
            Self::Uplc => "uplc",
            Self::UplcV3 => "uplc-v3",
        }
    }

    /// Returns whether the target is implemented in this release.
    pub fn implemented(self) -> bool {
        true
    }

    /// Returns `Ok(())` when the target can be used by the CLI.
    ///
    /// The `label` is included for consistency with future diagnostics and is
    /// currently preserved for API stability.
    pub fn ensure_supported(self, label: &str) -> Result<()> {
        let _ = label;
        Ok(())
    }

    /// Returns the backend compiler identifier string used in blueprints.
    pub fn compiler_target(self) -> Option<&'static str> {
        match self {
            Self::Preview => Some(PREVIEW_COMPILER_TARGET),
            Self::Uplc | Self::UplcV3 => Some(UPLC_COMPILER_TARGET),
        }
    }

    /// Returns whether this target is marked deployable in emitted metadata.
    pub fn cardano_deployable(self) -> Option<bool> {
        match self {
            Self::Preview => Some(PREVIEW_CARDANO_DEPLOYABLE),
            Self::Uplc | Self::UplcV3 => Some(UPLC_CARDANO_DEPLOYABLE),
        }
    }

    /// Returns the ledger version, or `None` for non-ledger preview output.
    pub fn plutus_version(self) -> Option<PlutusVersion> {
        match self {
            Self::Preview => None,
            Self::Uplc => Some(PlutusVersion::V2),
            Self::UplcV3 => Some(PlutusVersion::V3),
        }
    }
}

/// Renders validated IR to preview textual IR format.
pub fn render_preview_program(program: &Program) -> String {
    program.render()
}

/// Standardized message describing unsupported features in the UPLC path.
pub fn unsupported_uplc_message() -> &'static str {
    "target 'uplc' only supports validators that lower to the current serializable UPLC subset. Unsupported features still report explicit blockers."
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn preview_target_declares_non_deployable_text_ir() {
        assert_eq!(Target::Preview.name(), "preview");
        assert!(Target::Preview.implemented());
        assert_eq!(Target::Preview.compiler_target(), Some("aeri-text-ir"));
        assert_eq!(Target::Preview.cardano_deployable(), Some(false));
    }

    #[test]
    fn uplc_target_has_no_fake_metadata() {
        assert_eq!(Target::Uplc.name(), "uplc");
        assert!(Target::Uplc.implemented());
        assert_eq!(Target::Uplc.compiler_target(), Some("cardano-uplc-cbor"));
        assert_eq!(Target::Uplc.cardano_deployable(), Some(true));
    }
}