Skip to main content

aver/nan_value/
convert.rs

1use super::*;
2use std::collections::HashMap;
3
4use crate::value::Value;
5
6impl NanValue {
7    /// Convert old Value to NanValue, storing heap data in arena.
8    pub fn from_value(val: &Value, arena: &mut Arena) -> Self {
9        match val {
10            Value::Int(i) => NanValue::new_int(*i, arena),
11            Value::Float(f) => NanValue::new_float(*f),
12            Value::Bool(b) => NanValue::new_bool(*b),
13            Value::Unit => NanValue::UNIT,
14            Value::None => NanValue::NONE,
15            Value::Str(s) => NanValue::new_string_value(s, arena),
16            Value::Ok(inner) => {
17                let inner_nv = NanValue::from_value(inner, arena);
18                NanValue::new_ok_value(inner_nv, arena)
19            }
20            Value::Err(inner) => {
21                let inner_nv = NanValue::from_value(inner, arena);
22                NanValue::new_err_value(inner_nv, arena)
23            }
24            Value::Some(inner) => {
25                let inner_nv = NanValue::from_value(inner, arena);
26                NanValue::new_some_value(inner_nv, arena)
27            }
28            Value::Tuple(items) => {
29                let nv_items: Vec<_> = items
30                    .iter()
31                    .map(|v| NanValue::from_value(v, arena))
32                    .collect();
33                NanValue::new_tuple(arena.push_tuple(nv_items))
34            }
35            Value::List(aver_list) => {
36                let items: Vec<_> = aver_list
37                    .to_vec()
38                    .iter()
39                    .map(|v| NanValue::from_value(v, arena))
40                    .collect();
41                if items.is_empty() {
42                    NanValue::EMPTY_LIST
43                } else {
44                    NanValue::new_list(arena.push_list(items))
45                }
46            }
47            Value::Vector(vec) => {
48                let items: Vec<_> = vec.iter().map(|v| NanValue::from_value(v, arena)).collect();
49                if items.is_empty() {
50                    NanValue::EMPTY_VECTOR
51                } else {
52                    NanValue::new_vector(arena.push_vector(items))
53                }
54            }
55            Value::Map(map) => {
56                if map.is_empty() {
57                    return NanValue::EMPTY_MAP;
58                }
59                let mut nv_map = PersistentMap::new();
60                for (k, v) in map {
61                    let nk = NanValue::from_value(k, arena);
62                    let nv = NanValue::from_value(v, arena);
63                    nv_map = nv_map.insert(nk.map_key_hash(arena), (nk, nv));
64                }
65                let idx = arena.push(ArenaEntry::Map(nv_map));
66                NanValue::new_map(idx)
67            }
68            Value::Fn(f) => NanValue::new_fn(arena.push_fn(Rc::clone(f))),
69            Value::Builtin(name) => NanValue::new_builtin(arena.push_builtin(name)),
70            Value::Record { type_name, fields } => {
71                let type_id = arena.find_type_id(type_name).unwrap_or_else(|| {
72                    let field_names: Vec<String> = fields.iter().map(|(n, _)| n.clone()).collect();
73                    arena.register_record_type(type_name, field_names)
74                });
75                let nv_fields: Vec<_> = fields
76                    .iter()
77                    .map(|(_, v)| NanValue::from_value(v, arena))
78                    .collect();
79                NanValue::new_record(arena.push_record(type_id, nv_fields))
80            }
81            Value::Variant {
82                type_name,
83                variant,
84                fields,
85            } => {
86                let type_id = arena
87                    .find_type_id(type_name)
88                    .unwrap_or_else(|| arena.register_sum_type(type_name, vec![variant.clone()]));
89                let variant_id = arena
90                    .find_variant_id(type_id, variant)
91                    .unwrap_or_else(|| arena.register_variant_name(type_id, variant.clone()));
92                let nv_fields: Vec<_> = fields
93                    .iter()
94                    .map(|v| NanValue::from_value(v, arena))
95                    .collect();
96                if nv_fields.is_empty() {
97                    NanValue::new_nullary_variant(arena.push_nullary_variant_symbol(
98                        arena.find_ctor_id(type_id, variant_id).unwrap(),
99                    ))
100                } else {
101                    NanValue::new_variant(arena.push_variant(type_id, variant_id, nv_fields))
102                }
103            }
104            Value::Namespace { name, members } => {
105                let nv_members: Vec<_> = members
106                    .iter()
107                    .map(|(k, v)| (Rc::from(k.as_str()), NanValue::from_value(v, arena)))
108                    .collect();
109                let idx = arena.push(ArenaEntry::Namespace {
110                    name: Rc::from(name.as_str()),
111                    members: nv_members,
112                });
113                NanValue::new_namespace(idx)
114            }
115        }
116    }
117
118    /// Convert NanValue back to old Value (for interop during migration).
119    pub fn to_value(self, arena: &Arena) -> Value {
120        if self.is_float() {
121            return Value::Float(self.as_float());
122        }
123        if let Some((kind, inner)) = self.wrapper_parts(arena) {
124            let inner = inner.to_value(arena);
125            return match kind {
126                WRAP_SOME => Value::Some(Box::new(inner)),
127                WRAP_OK => Value::Ok(Box::new(inner)),
128                WRAP_ERR => Value::Err(Box::new(inner)),
129                _ => Value::Unit,
130            };
131        }
132        if let Some((type_id, variant_id, fields)) = self.variant_parts(arena) {
133            let type_name = arena.get_type_name(type_id).to_string();
134            let variant = arena.get_variant_name(type_id, variant_id).to_string();
135            let vals: Vec<Value> = fields.iter().map(|v| v.to_value(arena)).collect();
136            return Value::Variant {
137                type_name,
138                variant,
139                fields: vals.into(),
140            };
141        }
142        match self.tag() {
143            TAG_INT => Value::Int(self.as_int(arena)),
144            TAG_IMMEDIATE => match self.payload() {
145                IMM_FALSE => Value::Bool(false),
146                IMM_TRUE => Value::Bool(true),
147                IMM_UNIT => Value::Unit,
148                _ => Value::Unit,
149            },
150            TAG_NONE => Value::None,
151            TAG_SOME | TAG_OK | TAG_ERR => {
152                unreachable!("wrapper conversion handled before tag switch")
153            }
154            TAG_STRING => Value::Str(arena.get_string_value(self).to_string()),
155            TAG_LIST => {
156                let vals: Vec<Value> = arena
157                    .list_to_vec_value(self)
158                    .into_iter()
159                    .map(|v| v.to_value(arena))
160                    .collect();
161                Value::List(aver_rt::AverList::from_vec(vals))
162            }
163            TAG_VECTOR => {
164                let items = arena.vector_ref_value(self);
165                let vals: Vec<Value> = items.iter().map(|v| v.to_value(arena)).collect();
166                Value::Vector(aver_rt::AverVector::from_vec(vals))
167            }
168            TAG_TUPLE => {
169                let items = arena.get_tuple(self.arena_index());
170                Value::Tuple(items.iter().map(|v| v.to_value(arena)).collect())
171            }
172            TAG_MAP => {
173                let map = arena.map_ref_value(self);
174                let mut hm = HashMap::new();
175                for (k, v) in map.values() {
176                    hm.insert(k.to_value(arena), v.to_value(arena));
177                }
178                Value::Map(hm)
179            }
180            TAG_RECORD => {
181                let (type_id, fields) = arena.get_record(self.arena_index());
182                let type_name = arena.get_type_name(type_id).to_string();
183                let field_names = arena.get_field_names(type_id);
184                let pairs: Vec<(String, Value)> = field_names
185                    .iter()
186                    .zip(fields)
187                    .map(|(n, v)| (n.clone(), v.to_value(arena)))
188                    .collect();
189                Value::Record {
190                    type_name,
191                    fields: pairs.into(),
192                }
193            }
194            TAG_VARIANT => {
195                unreachable!("variant conversion handled before tag switch")
196            }
197            TAG_SYMBOL => match self.symbol_kind() {
198                SYMBOL_FN => Value::Fn(Rc::clone(arena.get_fn_rc(self.symbol_index()))),
199                SYMBOL_BUILTIN => {
200                    Value::Builtin(arena.get_builtin(self.symbol_index()).to_string())
201                }
202                SYMBOL_NAMESPACE => {
203                    let (name, members) = arena.get_namespace(self.symbol_index());
204                    let mut hm = HashMap::new();
205                    for (k, v) in members {
206                        hm.insert(k.to_string(), v.to_value(arena));
207                    }
208                    Value::Namespace {
209                        name: name.to_string(),
210                        members: hm,
211                    }
212                }
213                SYMBOL_NULLARY_VARIANT => {
214                    unreachable!("variant conversion handled before tag switch")
215                }
216                _ => Value::Unit,
217            },
218            _ => Value::Unit,
219        }
220    }
221}