Skip to main content

geam_core/runtime/
value.rs

1mod bit_array;
2mod capture;
3mod custom;
4mod external;
5mod function;
6mod inspection;
7mod list;
8
9use ecow::EcoString;
10use num_bigint::BigInt;
11
12use crate::plan::ValueType;
13
14pub use self::bit_array::{BitArrayValue, BitArrayValueLengthError};
15pub(crate) use self::capture::{CaptureListValue, CaptureValue};
16pub use self::custom::{CustomFieldValue, CustomValue};
17pub use self::external::{ExternalValue, ExternalValueIdentity};
18pub use self::function::FunctionValue;
19pub(crate) use self::function::{
20    BitArrayFunctionValue, BoolFunctionValue, CustomFunctionValue, CustomFunctionValueTarget,
21    ExternalFunctionValue, FloatFunctionValue, FunctionFunctionValue, FunctionValueKind,
22    GenericFunctionValue, IntFunctionValue, ListFunctionValue, NeverFunctionValue,
23    NilFunctionValue, StringFunctionValue, TupleFunctionValue, UtfCodepointFunctionValue,
24};
25pub use self::inspection::ValueInspection;
26pub use self::list::{ListValue, ListValueItemTypeMismatch};
27
28#[derive(Debug, Clone, PartialEq)]
29pub enum Value {
30    Int(BigInt),
31    Float(f64),
32    String(EcoString),
33    BitArray(BitArrayValue),
34    UtfCodepoint(char),
35    Custom(CustomValue),
36    External(ExternalValue),
37    Bool(bool),
38    Nil,
39    Tuple(Vec<Value>),
40    List(ListValue),
41    Function(FunctionValue),
42}
43
44impl Value {
45    pub fn inspect(&self) -> ValueInspection<'_> {
46        ValueInspection::new(self)
47    }
48
49    pub fn value_type(&self) -> ValueType {
50        match self {
51            Self::Int(_) => ValueType::Int,
52            Self::Float(_) => ValueType::Float,
53            Self::String(_) => ValueType::String,
54            Self::BitArray(_) => ValueType::BitArray,
55            Self::UtfCodepoint(_) => ValueType::UtfCodepoint,
56            Self::Custom(value) => ValueType::Custom(value.type_().clone()),
57            Self::External(value) => ValueType::External(value.type_().clone()),
58            Self::Bool(_) => ValueType::Bool,
59            Self::Nil => ValueType::Nil,
60            Self::Tuple(values) => ValueType::Tuple(values.iter().map(Self::value_type).collect()),
61            Self::List(value) => ValueType::List(Box::new(value.item_type())),
62            Self::Function(value) => ValueType::Function(Box::new(value.type_())),
63        }
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::{BitArrayValue, CustomValue, ExternalValue, ListValue, Value, ValueType};
70    use crate::host::HostExternalStore;
71    use crate::plan::{CustomType, CustomTypeName, ExternalType, ExternalTypeName};
72
73    #[test]
74    fn value_type_preserves_tuple_element_families() {
75        fn source_hash(
76            context: &crate::host::HostExternalHashing<'_>,
77            value: &crate::host::HostStoredValue<num_bigint::BigInt>,
78        ) -> u64 {
79            context.stored_value_hash(value)
80        }
81
82        fn inspect(
83            context: &crate::host::HostExternalInspection<'_>,
84            value: &crate::host::HostStoredValue<num_bigint::BigInt>,
85        ) -> ecow::EcoString {
86            context.inspect_stored_value(value)
87        }
88
89        assert_eq!(Value::Float(1.0).value_type(), ValueType::Float);
90        assert_eq!(Value::String("one".into()).value_type(), ValueType::String);
91        assert_eq!(
92            Value::BitArray(BitArrayValue::from_bytes(vec![1])).value_type(),
93            ValueType::BitArray,
94        );
95        assert_eq!(
96            Value::UtfCodepoint('\u{10ffff}').value_type(),
97            ValueType::UtfCodepoint,
98        );
99        let custom_type = CustomType::new(
100            CustomTypeName::new("geam".into(), "main".into(), "Boxed".into()),
101            Vec::new(),
102        );
103        assert_eq!(
104            Value::Custom(CustomValue::from_evaluated(
105                custom_type.clone(),
106                "Boxed".into(),
107                0,
108                Vec::new(),
109            ))
110            .value_type(),
111            ValueType::Custom(custom_type),
112        );
113        let external_type = ExternalType::new(
114            ExternalTypeName::new("application".into(), "main".into(), "Resource".into()),
115            Vec::new(),
116        );
117        let store = HostExternalStore::default();
118        let source_equal =
119            |context: &crate::host::HostExternalEquality<'_>,
120             left: &crate::host::HostStoredValue<num_bigint::BigInt>,
121             right: &crate::host::HostStoredValue<num_bigint::BigInt>| {
122                context.stored_values_equal(left, right)
123            };
124        let first = store.insert(
125            crate::host::HostStoredValue::new(crate::runtime::StoredRuntimeValue::test_int(
126                7.into(),
127            )),
128            source_equal,
129            source_hash,
130            inspect,
131        );
132        let equal = store.insert(
133            crate::host::HostStoredValue::new(crate::runtime::StoredRuntimeValue::test_int(
134                7.into(),
135            )),
136            source_equal,
137            source_hash,
138            inspect,
139        );
140        let stored_equal =
141            |left: &crate::runtime::StoredRuntimeValue,
142             right: &crate::runtime::StoredRuntimeValue| left.value() == right.value();
143        let equality = crate::host::HostExternalEquality::new(&stored_equal);
144        assert!(first.source_equal(&equality, &equal));
145        let stored_hash = |_: &crate::runtime::StoredRuntimeValue| 7;
146        let stored_inspect = |_: &crate::runtime::StoredRuntimeValue| "Resource(7)".into();
147        assert_eq!(
148            first.source_hash(&crate::host::HostExternalHashing::new(&stored_hash)),
149            7,
150        );
151        assert_eq!(
152            first.inspection(&crate::host::HostExternalInspection::new(&stored_inspect)),
153            "Resource(7)",
154        );
155        assert_eq!(
156            Value::External(ExternalValue::from_evaluated(
157                external_type.clone(),
158                first,
159                "Resource(7)".into(),
160            ))
161            .value_type(),
162            ValueType::External(external_type),
163        );
164        assert_eq!(Value::Bool(true).value_type(), ValueType::Bool);
165        assert_eq!(Value::Nil.value_type(), ValueType::Nil);
166        assert_eq!(
167            Value::Tuple(vec![Value::Int(1.into()), Value::String("one".into())]).value_type(),
168            ValueType::Tuple(vec![ValueType::Int, ValueType::String]),
169        );
170        assert_eq!(
171            Value::List(ListValue::int(vec![1.into()])).value_type(),
172            ValueType::List(Box::new(ValueType::Int)),
173        );
174        let function = super::FunctionValue::new(
175            crate::plan::execution::function::RuntimeFunctionId::Core(
176                crate::plan::execution::function::CoreRuntimeFunctionId::Int(
177                    crate::plan::execution::function::IntFunctionId(0),
178                ),
179            ),
180            Vec::new(),
181            crate::plan::FunctionType::new(Vec::new(), ValueType::Int),
182        );
183        assert_eq!(
184            Value::Function(function).value_type(),
185            ValueType::Function(Box::new(crate::plan::FunctionType::new(
186                Vec::new(),
187                ValueType::Int,
188            ))),
189        );
190    }
191}