selfware 0.2.2

Your personal AI workshop — software you own, software that lasts
Documentation
//! Value -- runtime value representation and conversions.

#![allow(dead_code, unused_imports, unused_variables)]

use std::collections::HashMap;

use super::ast::AstNode;

/// Runtime value
#[derive(Debug, Clone)]
pub enum Value {
    Null,
    Boolean(bool),
    Integer(i64),
    Float(f64),
    String(String),
    Array(Vec<Value>),
    Object(HashMap<String, Value>),
    Function {
        params: Vec<String>,
        body: Vec<AstNode>,
    },
    StepResult {
        name: String,
        success: bool,
        output: String,
        error: Option<String>,
    },
}

impl Value {
    /// Convert to boolean
    pub fn as_bool(&self) -> bool {
        match self {
            Value::Null => false,
            Value::Boolean(b) => *b,
            Value::Integer(n) => *n != 0,
            Value::Float(n) => *n != 0.0,
            Value::String(s) => !s.is_empty(),
            Value::Array(a) => !a.is_empty(),
            Value::Object(o) => !o.is_empty(),
            Value::Function { .. } => true,
            Value::StepResult { success, .. } => *success,
        }
    }

    /// Convert to string
    pub fn as_string(&self) -> String {
        match self {
            Value::Null => "null".to_string(),
            Value::Boolean(b) => b.to_string(),
            Value::Integer(n) => n.to_string(),
            Value::Float(n) => n.to_string(),
            Value::String(s) => s.clone(),
            Value::Array(a) => format!(
                "[{}]",
                a.iter()
                    .map(|v| v.as_string())
                    .collect::<Vec<_>>()
                    .join(", ")
            ),
            Value::Object(_) => "[object]".to_string(),
            Value::Function { .. } => "[function]".to_string(),
            Value::StepResult { output, .. } => output.clone(),
        }
    }
}

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

    #[test]
    fn test_value_as_bool() {
        assert!(!Value::Null.as_bool());
        assert!(Value::Boolean(true).as_bool());
        assert!(!Value::Boolean(false).as_bool());
        assert!(Value::Integer(1).as_bool());
        assert!(!Value::Integer(0).as_bool());
        assert!(Value::String("hello".to_string()).as_bool());
        assert!(!Value::String(String::new()).as_bool());
    }

    #[test]
    fn test_value_as_string() {
        assert_eq!(Value::Integer(42).as_string(), "42");
        assert_eq!(Value::Boolean(true).as_string(), "true");
        assert_eq!(Value::String("test".to_string()).as_string(), "test");
    }

    #[test]
    fn test_value_as_bool_float() {
        assert!(Value::Float(1.0).as_bool());
        assert!(!Value::Float(0.0).as_bool());
        assert!(Value::Float(-1.5).as_bool());
    }

    #[test]
    fn test_value_as_bool_array() {
        assert!(Value::Array(vec![Value::Integer(1)]).as_bool());
        assert!(!Value::Array(vec![]).as_bool());
    }

    #[test]
    fn test_value_as_bool_object() {
        let mut map = HashMap::new();
        map.insert("key".to_string(), Value::Integer(1));
        assert!(Value::Object(map).as_bool());
        assert!(!Value::Object(HashMap::new()).as_bool());
    }

    #[test]
    fn test_value_as_bool_function() {
        assert!(Value::Function {
            params: vec![],
            body: vec![],
        }
        .as_bool());
    }

    #[test]
    fn test_value_as_bool_step_result() {
        assert!(Value::StepResult {
            name: "test".to_string(),
            success: true,
            output: "ok".to_string(),
            error: None,
        }
        .as_bool());

        assert!(!Value::StepResult {
            name: "test".to_string(),
            success: false,
            output: "".to_string(),
            error: Some("err".to_string()),
        }
        .as_bool());
    }

    #[test]
    fn test_value_as_string_float() {
        let s = Value::Float(3.15).as_string();
        assert!(s.contains("3.15"));
    }

    #[test]
    fn test_value_as_string_null() {
        assert_eq!(Value::Null.as_string(), "null");
    }

    #[test]
    fn test_value_as_string_array() {
        let arr = Value::Array(vec![Value::Integer(1), Value::Integer(2)]);
        let s = arr.as_string();
        assert!(s.starts_with('['));
        assert!(s.ends_with(']'));
        assert!(s.contains("1"));
        assert!(s.contains("2"));
    }

    #[test]
    fn test_value_as_string_object() {
        assert_eq!(Value::Object(HashMap::new()).as_string(), "[object]");
    }

    #[test]
    fn test_value_as_string_function() {
        assert_eq!(
            Value::Function {
                params: vec![],
                body: vec![],
            }
            .as_string(),
            "[function]"
        );
    }

    #[test]
    fn test_value_as_string_step_result() {
        let sr = Value::StepResult {
            name: "build".to_string(),
            success: true,
            output: "compiled".to_string(),
            error: None,
        };
        assert_eq!(sr.as_string(), "compiled");
    }
}