glyph-types 0.0.1

Core type definitions and value system for the Glyph programming language
Documentation
//! Runtime value representation for Glyph

use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;

/// Runtime values in Glyph
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Value {
    /// Integer value
    Int(i64),

    /// Floating point value
    Float(f64),

    /// String value
    Str(String),

    /// Boolean value
    Bool(bool),

    /// Byte array
    Bytes(Vec<u8>),

    /// None/unit value
    None,

    /// List of values
    List(Vec<Value>),

    /// Dictionary of string keys to values
    Dict(HashMap<String, Value>),

    /// Optional value
    Optional(Option<Box<Value>>),

    /// Promise (async computation)
    Promise(PromiseState),

    /// Result type
    Result(Result<Box<Value>, Box<Value>>),

    /// Function (not directly serializable)
    #[serde(skip)]
    Function {
        params: Vec<String>,
        body: Vec<u8>, // Bytecode or AST reference
    },
}

/// State of a promise
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum PromiseState {
    Pending,
    Resolved(Box<Value>),
    Rejected(String),
}

impl Value {
    /// Get the type of this value
    pub fn get_type(&self) -> crate::Type {
        use crate::Type;

        match self {
            Value::Int(_) => Type::Int,
            Value::Float(_) => Type::Float,
            Value::Str(_) => Type::Str,
            Value::Bool(_) => Type::Bool,
            Value::Bytes(_) => Type::Bytes,
            Value::None => Type::Unit,
            Value::List(items) => {
                // Infer list type from first element or use Unknown
                let inner = items.first().map(|v| v.get_type()).unwrap_or(Type::Unknown);
                Type::List(Box::new(inner))
            }
            Value::Dict(map) => {
                // All keys are strings, infer value type
                let value_type = map
                    .values()
                    .next()
                    .map(|v| v.get_type())
                    .unwrap_or(Type::Unknown);
                Type::Dict(Box::new(Type::Str), Box::new(value_type))
            }
            Value::Optional(opt) => {
                let inner = opt.as_ref().map(|v| v.get_type()).unwrap_or(Type::Unknown);
                Type::Optional(Box::new(inner))
            }
            Value::Promise(_) => Type::Promise(Box::new(Type::Unknown)),
            Value::Result(res) => match res {
                Ok(v) => Type::Result(Box::new(v.get_type()), Box::new(Type::Unknown)),
                Err(e) => Type::Result(Box::new(Type::Unknown), Box::new(e.get_type())),
            },
            Value::Function { params, .. } => Type::Function {
                params: params
                    .iter()
                    .map(|name| (name.clone(), Type::Unknown))
                    .collect(),
                return_type: Box::new(Type::Unknown),
            },
        }
    }

    /// Check if this value is truthy
    pub fn is_truthy(&self) -> bool {
        match self {
            Value::Bool(b) => *b,
            Value::None => false,
            Value::Int(i) => *i != 0,
            Value::Float(f) => *f != 0.0,
            Value::Str(s) => !s.is_empty(),
            Value::List(l) => !l.is_empty(),
            Value::Dict(d) => !d.is_empty(),
            Value::Bytes(b) => !b.is_empty(),
            Value::Optional(opt) => opt.is_some(),
            _ => true,
        }
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Value::Int(i) => write!(f, "{i}"),
            Value::Float(fl) => write!(f, "{fl}"),
            Value::Str(s) => write!(f, "\"{s}\""),
            Value::Bool(b) => write!(f, "{b}"),
            Value::Bytes(b) => write!(f, "bytes({})", b.len()),
            Value::None => write!(f, "None"),
            Value::List(items) => {
                write!(f, "[")?;
                for (i, item) in items.iter().enumerate() {
                    if i > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "{item}")?;
                }
                write!(f, "]")
            }
            Value::Dict(map) => {
                write!(f, "{{")?;
                for (i, (k, v)) in map.iter().enumerate() {
                    if i > 0 {
                        write!(f, ", ")?;
                    }
                    write!(f, "\"{k}\": {v}")?;
                }
                write!(f, "}}")
            }
            Value::Optional(opt) => match opt {
                Some(v) => write!(f, "Some({v})"),
                None => write!(f, "None"),
            },
            Value::Promise(state) => match state {
                PromiseState::Pending => write!(f, "Promise<pending>"),
                PromiseState::Resolved(v) => write!(f, "Promise<resolved: {v}>"),
                PromiseState::Rejected(e) => write!(f, "Promise<rejected: {e}>")
            },
            Value::Result(res) => match res {
                Ok(v) => write!(f, "Ok({v})"),
                Err(e) => write!(f, "Err({e})"),
            },
            Value::Function { params, .. } => {
                write!(f, "function({})", params.join(", "))
            }
        }
    }
}