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(arena.push_string(s)),
16            Value::Ok(inner) => {
17                let inner_nv = NanValue::from_value(inner, arena);
18                let idx = arena.push_boxed(inner_nv);
19                NanValue::new_ok(idx)
20            }
21            Value::Err(inner) => {
22                let inner_nv = NanValue::from_value(inner, arena);
23                let idx = arena.push_boxed(inner_nv);
24                NanValue::new_err(idx)
25            }
26            Value::Some(inner) => {
27                let inner_nv = NanValue::from_value(inner, arena);
28                let idx = arena.push_boxed(inner_nv);
29                NanValue::new_some(idx)
30            }
31            Value::Tuple(items) => {
32                let nv_items: Vec<_> = items
33                    .iter()
34                    .map(|v| NanValue::from_value(v, arena))
35                    .collect();
36                NanValue::new_tuple(arena.push_tuple(nv_items))
37            }
38            Value::List(aver_list) => {
39                let items: Vec<_> = aver_list
40                    .to_vec()
41                    .iter()
42                    .map(|v| NanValue::from_value(v, arena))
43                    .collect();
44                NanValue::new_list(arena.push_list(items))
45            }
46            Value::Map(map) => {
47                let mut nv_map = PersistentMap::new();
48                for (k, v) in map {
49                    let nk = NanValue::from_value(k, arena);
50                    let nv = NanValue::from_value(v, arena);
51                    nv_map.insert(nk.map_key_hash(arena), (nk, nv));
52                }
53                let idx = arena.push(ArenaEntry::Map(nv_map));
54                NanValue::new_map(idx)
55            }
56            Value::Fn(f) => NanValue::new_fn(arena.push_fn(Rc::clone(f))),
57            Value::Builtin(name) => NanValue::new_builtin(arena.push_builtin(name)),
58            Value::Record { type_name, fields } => {
59                let type_id = arena.find_type_id(type_name).unwrap_or_else(|| {
60                    let field_names: Vec<String> = fields.iter().map(|(n, _)| n.clone()).collect();
61                    arena.register_record_type(type_name, field_names)
62                });
63                let nv_fields: Vec<_> = fields
64                    .iter()
65                    .map(|(_, v)| NanValue::from_value(v, arena))
66                    .collect();
67                NanValue::new_record(arena.push_record(type_id, nv_fields))
68            }
69            Value::Variant {
70                type_name,
71                variant,
72                fields,
73            } => {
74                let type_id = arena
75                    .find_type_id(type_name)
76                    .unwrap_or_else(|| arena.register_sum_type(type_name, vec![variant.clone()]));
77                let variant_id = arena.find_variant_id(type_id, variant).unwrap_or_else(|| {
78                    // Register new variant dynamically
79                    let variants = &mut arena.type_variant_names[type_id as usize];
80                    let id = variants.len() as u16;
81                    variants.push(variant.clone());
82                    id
83                });
84                let nv_fields: Vec<_> = fields
85                    .iter()
86                    .map(|v| NanValue::from_value(v, arena))
87                    .collect();
88                NanValue::new_variant(arena.push_variant(type_id, variant_id, nv_fields))
89            }
90            Value::Namespace { name, members } => {
91                let nv_members: Vec<_> = members
92                    .iter()
93                    .map(|(k, v)| (Rc::from(k.as_str()), NanValue::from_value(v, arena)))
94                    .collect();
95                let idx = arena.push(ArenaEntry::Namespace {
96                    name: Rc::from(name.as_str()),
97                    members: nv_members,
98                });
99                NanValue::new_namespace(idx)
100            }
101        }
102    }
103
104    /// Convert NanValue back to old Value (for interop during migration).
105    pub fn to_value(self, arena: &Arena) -> Value {
106        if self.is_float() {
107            return Value::Float(self.as_float());
108        }
109        match self.tag() {
110            TAG_INT => Value::Int(self.as_int(arena)),
111            TAG_IMMEDIATE => match self.payload() {
112                IMM_FALSE => Value::Bool(false),
113                IMM_TRUE => Value::Bool(true),
114                IMM_UNIT => Value::Unit,
115                IMM_NONE => Value::None,
116                _ => Value::Unit,
117            },
118            TAG_WRAPPER => {
119                let inner = arena.get_boxed(self.wrapper_index()).to_value(arena);
120                match self.wrapper_kind() {
121                    WRAP_SOME => Value::Some(Box::new(inner)),
122                    WRAP_OK => Value::Ok(Box::new(inner)),
123                    WRAP_ERR => Value::Err(Box::new(inner)),
124                    _ => Value::Unit,
125                }
126            }
127            TAG_STRING => Value::Str(arena.get_string(self.arena_index()).to_string()),
128            TAG_LIST => {
129                let vals: Vec<Value> = arena
130                    .list_to_vec(self.arena_index())
131                    .into_iter()
132                    .map(|v| v.to_value(arena))
133                    .collect();
134                Value::List(aver_rt::AverList::from_vec(vals))
135            }
136            TAG_TUPLE => {
137                let items = arena.get_tuple(self.arena_index());
138                Value::Tuple(items.iter().map(|v| v.to_value(arena)).collect())
139            }
140            TAG_MAP => {
141                let map = arena.get_map(self.arena_index());
142                let mut hm = HashMap::new();
143                for (k, v) in map.values() {
144                    hm.insert(k.to_value(arena), v.to_value(arena));
145                }
146                Value::Map(hm)
147            }
148            TAG_RECORD => {
149                let (type_id, fields) = arena.get_record(self.arena_index());
150                let type_name = arena.get_type_name(type_id).to_string();
151                let field_names = arena.get_field_names(type_id);
152                let pairs: Vec<(String, Value)> = field_names
153                    .iter()
154                    .zip(fields)
155                    .map(|(n, v)| (n.clone(), v.to_value(arena)))
156                    .collect();
157                Value::Record {
158                    type_name,
159                    fields: pairs.into(),
160                }
161            }
162            TAG_VARIANT => {
163                let (type_id, variant_id, fields) = arena.get_variant(self.arena_index());
164                let type_name = arena.get_type_name(type_id).to_string();
165                let variant = arena.get_variant_name(type_id, variant_id).to_string();
166                let vals: Vec<Value> = fields.iter().map(|v| v.to_value(arena)).collect();
167                Value::Variant {
168                    type_name,
169                    variant,
170                    fields: vals.into(),
171                }
172            }
173            TAG_FN => Value::Fn(Rc::clone(arena.get_fn_rc(self.arena_index()))),
174            TAG_BUILTIN => Value::Builtin(arena.get_builtin(self.arena_index()).to_string()),
175            TAG_NAMESPACE => {
176                let (name, members) = arena.get_namespace(self.arena_index());
177                let mut hm = HashMap::new();
178                for (k, v) in members {
179                    hm.insert(k.to_string(), v.to_value(arena));
180                }
181                Value::Namespace {
182                    name: name.to_string(),
183                    members: hm,
184                }
185            }
186            _ => Value::Unit,
187        }
188    }
189}