rimu_value/
lib.rs

1mod environment;
2mod eval;
3mod from;
4mod function;
5mod native;
6mod number;
7mod serde;
8
9use indexmap::IndexMap;
10use rimu_meta::{Span, Spanned};
11
12use std::fmt::{Debug, Display};
13
14pub use self::environment::{Environment, EnvironmentError};
15pub use self::eval::EvalError;
16pub use self::function::{Function, FunctionBody};
17pub use self::native::NativeFunction;
18pub use self::number::Number;
19pub use self::serde::{
20    convert, from_serde_value, to_serde_value, SerdeValue, SerdeValueError, SerdeValueList,
21    SerdeValueObject,
22};
23
24pub type ValueList = Vec<SpannedValue>;
25pub type ValueObject = IndexMap<String, SpannedValue>;
26
27#[derive(Default, Clone, PartialEq)]
28pub enum Value {
29    #[default]
30    Null,
31    Boolean(bool),
32    String(String),
33    Number(Number),
34    Function(Function),
35    List(ValueList),
36    Object(ValueObject),
37}
38
39pub type SpannedValue = Spanned<Value>;
40
41impl From<SpannedValue> for SerdeValue {
42    fn from(value: SpannedValue) -> Self {
43        value.into_inner().into()
44    }
45}
46
47impl From<Value> for SerdeValue {
48    fn from(value: Value) -> Self {
49        match value {
50            Value::Null => SerdeValue::Null,
51            Value::Boolean(boolean) => SerdeValue::Boolean(boolean),
52            Value::String(string) => SerdeValue::String(string),
53            Value::Number(number) => SerdeValue::Number(number),
54            Value::Function(function) => SerdeValue::Function(function),
55            Value::List(list) => SerdeValue::List(convert_value_list_to_serde_value_list(list)),
56            Value::Object(object) => {
57                SerdeValue::Object(convert_value_object_to_serde_value_object(object))
58            }
59        }
60    }
61}
62
63pub fn convert_value_list_to_serde_value_list(list: ValueList) -> SerdeValueList {
64    list.iter().map(|item| item.clone().into()).collect()
65}
66
67pub fn convert_value_object_to_serde_value_object(object: ValueObject) -> SerdeValueObject {
68    SerdeValueObject::from_iter(
69        object
70            .iter()
71            .map(|(key, value)| (key.clone(), value.clone().into()))
72            .collect::<Vec<_>>(),
73    )
74}
75
76impl SerdeValue {
77    pub fn with_span(&self, span: Span) -> SpannedValue {
78        let value = match self {
79            SerdeValue::Null => Value::Null,
80            SerdeValue::Boolean(boolean) => Value::Boolean(boolean.to_owned()),
81            SerdeValue::String(string) => Value::String(string.to_owned()),
82            SerdeValue::Number(number) => Value::Number(number.to_owned()),
83            SerdeValue::Function(function) => Value::Function(function.to_owned()),
84            SerdeValue::List(list) => Value::List(
85                list.iter()
86                    .map(|item| item.clone().with_span(span.clone()))
87                    .collect(),
88            ),
89            SerdeValue::Object(object) => Value::Object(ValueObject::from_iter(
90                object
91                    .iter()
92                    .map(|(key, value)| (key.clone(), value.clone().with_span(span.clone())))
93                    .collect::<Vec<_>>(),
94            )),
95        };
96        Spanned::new(value, span)
97    }
98}
99
100impl Debug for Value {
101    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102        match self {
103            Value::Null => formatter.write_str("Null"),
104            Value::Boolean(boolean) => match boolean {
105                true => formatter.write_str("true"),
106                false => formatter.write_str("false"),
107            },
108            Value::String(string) => write!(formatter, "String({:?})", string),
109            Value::Number(number) => write!(formatter, "Number({})", number),
110            Value::Function(function) => {
111                write!(formatter, "Function({:?})", function)
112            }
113            Value::List(list) => {
114                formatter.write_str("List ")?;
115                formatter.debug_list().entries(list).finish()
116            }
117            Value::Object(object) => {
118                formatter.write_str("Object ")?;
119                formatter.debug_map().entries(object).finish()
120            }
121        }
122    }
123}
124
125impl Display for Value {
126    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
127        match self {
128            Value::Null => write!(f, "null"),
129            Value::Boolean(boolean) => write!(f, "{}", boolean),
130            Value::String(string) => write!(f, "{}", string),
131            Value::Number(number) => write!(f, "{}", number),
132            Value::Function(function) => write!(f, "{}", function),
133            Value::List(list) => {
134                let items = list
135                    .iter()
136                    .map(|value| value.to_string())
137                    .collect::<Vec<String>>()
138                    .join(", ");
139                write!(f, "[{}]", items)
140            }
141            Value::Object(object) => {
142                let entries = object
143                    .iter()
144                    .map(|(key, value)| format!("\"{}\": {}", key, value))
145                    .collect::<Vec<String>>()
146                    .join(", ");
147                write!(f, "{{{}}}", entries)
148            }
149        }
150    }
151}
152
153/// Everything except `false` and `null' is truthy.
154impl From<Value> for bool {
155    fn from(value: Value) -> Self {
156        #[allow(clippy::match_like_matches_macro)]
157        match value {
158            Value::Null | Value::Boolean(false) => false,
159            _ => true,
160        }
161    }
162}