Skip to main content

rl_lang/interpreter/
values.rs

1//! Runtime value types for the rl interpreter.
2
3use crate::{
4    ast::statements::{Param, Statement, TypeAnnotation},
5    interpreter::evaluator::EnvironmentItem,
6};
7use std::{cell::RefCell, collections::HashMap, fmt, rc::Rc};
8
9/// A runtime value produced by evaluating an rl expression.
10#[derive(Debug, Clone, PartialEq)]
11pub enum Value {
12    /// A 64-bit signed integer.
13    Integer(i64),
14    /// A 64-bit float.
15    Float(f64),
16    /// A UTF-8 string.
17    String(String),
18    /// A boolean.
19    Bool(bool),
20    /// A single unsigned byte (`u8`).
21    Byte(u8),
22    /// A single Unicode character.
23    Char(char),
24    /// A homogeneous array of values with a tracked element type.
25    Values {
26        /// The declared element type of this array.
27        items_type: TypeAnnotation,
28        items: Vec<Value>,
29    },
30    /// The absence of a value - equivalent to `null` in rl source.
31    Null,
32
33    /// A first-class function or lambda value, carrying its closure environment.
34    Function(Rc<FunctionData>),
35
36    /// A heterogeneous tuple of values.
37    Tuple(Vec<Value>),
38    /// An error value wrapping any non-error value.
39    Error(Box<Value>),
40    Ok(Box<Value>),
41    Err(Box<Value>),
42
43    Struct {
44        name: String,
45        fields: Rc<RefCell<Vec<(String, Value)>>>,
46    },
47    Enum {
48        name: String,
49        variant: String,
50    },
51
52    Map {
53        key_type: TypeAnnotation,
54        value_type: TypeAnnotation,
55        entries: Rc<RefCell<HashMap<MapKey, Value>>>,
56    },
57    Set {
58        /// The declared element type of this set.
59        items_type: TypeAnnotation,
60        items: Vec<Value>,
61    },
62}
63
64/// Payload for `Value::Function`
65#[derive(Debug, Clone, PartialEq)]
66pub struct FunctionData {
67    pub params: Rc<Vec<Param>>,
68    pub body: Rc<Vec<Statement>>,
69    /// Declared return type; `None` for lambdas without an annotation.
70    pub return_type: Option<TypeAnnotation>,
71    /// The captured environment frames at the point of lambda definition.
72    pub captured_env: Vec<Vec<EnvironmentItem>>,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Hash)]
76pub enum MapKey {
77    Integer(i64),
78    String(String),
79    Bool(bool),
80    Byte(u8),
81    Char(char),
82}
83
84impl MapKey {
85    pub fn from_value(value: &Value) -> Option<MapKey> {
86        match value {
87            Value::Integer(i) => Some(MapKey::Integer(*i)),
88            Value::String(s) => Some(MapKey::String(s.clone())),
89            Value::Bool(b) => Some(MapKey::Bool(*b)),
90            Value::Byte(b) => Some(MapKey::Byte(*b)),
91            Value::Char(c) => Some(MapKey::Char(*c)),
92            _ => None,
93        }
94    }
95
96    pub fn into_value(self) -> Value {
97        match self {
98            MapKey::Integer(i) => Value::Integer(i),
99            MapKey::String(s) => Value::String(s),
100            MapKey::Bool(b) => Value::Bool(b),
101            MapKey::Byte(b) => Value::Byte(b),
102            MapKey::Char(c) => Value::Char(c),
103        }
104    }
105}
106
107impl Value {
108    /// Human-readable type name used in error labels (e.g. "int", "bool", "array").
109    pub fn type_name(&self) -> &'static str {
110        match self {
111            Value::Integer(_) => "int",
112            Value::Float(_) => "float",
113            Value::String(_) => "string",
114            Value::Bool(_) => "bool",
115            Value::Byte(_) => "byte",
116            Value::Char(_) => "char",
117            Value::Values { .. } => "array",
118            Value::Map { .. } => "map",
119            Value::Null => "null",
120            Value::Function { .. } => "function",
121            Value::Tuple(_) => "tuple",
122            Value::Error(_) => "error",
123            Value::Ok(_) => "ok",
124            Value::Err(_) => "err",
125            Value::Struct { .. } => "record",
126            Value::Enum { .. } => "tag",
127            Value::Set { .. } => "set",
128        }
129    }
130
131    pub fn is_ok(&self) -> bool {
132        matches!(self, Value::Ok(_))
133    }
134    pub fn is_err(&self) -> bool {
135        matches!(self, Value::Err(_))
136    }
137}
138
139impl fmt::Display for Value {
140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
141        match self {
142            Value::Integer(i) => write!(f, "{}", i),
143            Value::Float(fl) => write!(f, "{}", fl),
144            Value::String(s) => write!(f, "{}", s),
145            Value::Bool(b) => write!(f, "{}", b),
146            Value::Byte(b) => write!(f, "{}", b),
147            Value::Char(c) => write!(f, "'{}'", c),
148            Value::Values { items, .. } => {
149                let formatted: Vec<String> = items.iter().map(|v| v.to_string()).collect();
150                write!(f, "[{}]", formatted.join(", "))
151            }
152            Value::Null => write!(f, "null"),
153            Value::Function(data) => {
154                let mut params_name = vec![];
155                for param in data.params.iter() {
156                    params_name.push(param.param_name.clone());
157                }
158                write!(f, "<fn({})>", params_name.join(", "))
159            }
160            Value::Tuple(items) => {
161                let formatted: Vec<String> = items.iter().map(|v| v.to_string()).collect();
162                write!(f, "({})", formatted.join(", "))
163            }
164            Value::Error(inner) => write!(f, "error({})", inner),
165            Value::Ok(inner) => write!(f, "ok({})", inner),
166            Value::Err(inner) => write!(f, "err({})", inner),
167            Value::Struct { name, fields } => {
168                let fields = fields.borrow();
169                let formatted: Vec<String> = fields
170                    .iter()
171                    .map(|(field_name, value)| format!("{}: {}", field_name, value))
172                    .collect();
173                write!(f, "{} {{ {} }}", name, formatted.join(", "))
174            }
175            Value::Enum { name, variant } => write!(f, "{}.{}", name, variant),
176            Value::Map { entries, .. } => {
177                let entries = entries.borrow();
178                let formatted: Vec<String> = entries
179                    .iter()
180                    .map(|(k, v)| format!("{}: {}", k.clone().into_value(), v))
181                    .collect();
182                write!(f, "{{{}}}", formatted.join(", "))
183            }
184            Value::Set { items, .. } => {
185                let formatted: Vec<String> = items.iter().map(|v| v.to_string()).collect();
186                write!(f, "{{{}}}", formatted.join(", "))
187            }
188        }
189    }
190}