Refactor map and record representation
Replaces the use of `BTreeMap` and `HashMap` for maps and records with `Vec<(Keyword, Value)>` and `Vec<(Keyword, StaticType)>`. This simplifies the data structure and allows for ordered iteration, which is important for serialization and comparison. Also updates the `unpack` function in `vm.rs` to handle records as well as lists when destructuring.
This commit is contained in:
+29
-14
@@ -1,6 +1,5 @@
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::any::Any;
|
||||
use crate::ast::compiler::bound_nodes::{Address, BoundKind, TypedNode};
|
||||
use crate::ast::types::{Value, Object};
|
||||
@@ -318,13 +317,13 @@ macro_rules! dispatch_eval {
|
||||
},
|
||||
|
||||
BoundKind::Map { entries } => {
|
||||
let mut map = HashMap::new();
|
||||
let mut map = Vec::with_capacity(entries.len());
|
||||
for (k, v) in entries {
|
||||
let key = $self.$eval_method($($observer,)? k)?;
|
||||
let val = $self.$eval_method($($observer,)? v)?;
|
||||
|
||||
if let Value::Keyword(kw) = key {
|
||||
map.insert(kw, val);
|
||||
map.push((kw, val));
|
||||
} else {
|
||||
return Err(format!("Map key must be keyword, got {}", key));
|
||||
}
|
||||
@@ -678,19 +677,35 @@ impl VM {
|
||||
Ok(())
|
||||
}
|
||||
BoundKind::Tuple { elements } => {
|
||||
// If the current value at offset is a List, we dive into it.
|
||||
// Otherwise, we assume the list was already flattened (e.g. by Specializer).
|
||||
if let Some(Value::List(l)) = values.get(*offset) {
|
||||
*offset += 1;
|
||||
let mut sub_offset = 0;
|
||||
for el in elements {
|
||||
self.unpack(el, l, &mut sub_offset)?;
|
||||
}
|
||||
} else {
|
||||
for el in elements {
|
||||
self.unpack(el, values, offset)?;
|
||||
// If the current value at offset is a List or Record, we dive into it.
|
||||
// Otherwise, we assume the sequence was already flattened (e.g. by Specializer).
|
||||
if let Some(val) = values.get(*offset) {
|
||||
match val {
|
||||
Value::List(l) => {
|
||||
*offset += 1;
|
||||
let mut sub_offset = 0;
|
||||
for el in elements {
|
||||
self.unpack(el, l, &mut sub_offset)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
Value::Record(r) => {
|
||||
*offset += 1;
|
||||
let mut sub_offset = 0;
|
||||
// Treat record values as a tuple sequence in definition order
|
||||
let record_values: Vec<_> = r.iter().map(|(_, v)| v.clone()).collect();
|
||||
for el in elements {
|
||||
self.unpack(el, &record_values, &mut sub_offset)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
for el in elements {
|
||||
self.unpack(el, values, offset)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
_ => Err("Invalid node in parameter pattern".to_string()),
|
||||
|
||||
Reference in New Issue
Block a user