Refactor Record and List to use TupleData
The `Value::List` and `Value::Record` variants have been consolidated into a single `Value::Tuple` variant. This new variant uses a `TupleData` struct to store values and an optional `Rc<Vec<Keyword>>` for keys, allowing it to represent both ordered lists/tuples and key-value records. This change simplifies the internal representation and improves performance by allowing schema sharing for records. It also includes updates to the compiler, runtime, and tests to reflect the new structure.
This commit is contained in:
+15
-28
@@ -313,22 +313,24 @@ macro_rules! dispatch_eval {
|
||||
for e in elements {
|
||||
vals.push($self.$eval_method($($observer,)? e)?);
|
||||
}
|
||||
Ok(Value::List(Rc::new(vals)))
|
||||
Ok(Value::make_list(vals))
|
||||
},
|
||||
|
||||
BoundKind::Map { entries } => {
|
||||
let mut map = Vec::with_capacity(entries.len());
|
||||
let mut keys = Vec::with_capacity(entries.len());
|
||||
let mut values = 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.push((kw, val));
|
||||
keys.push(kw);
|
||||
values.push(val);
|
||||
} else {
|
||||
return Err(format!("Map key must be keyword, got {}", key));
|
||||
}
|
||||
}
|
||||
Ok(Value::Record(Rc::new(map)))
|
||||
Ok(Value::make_record(keys, values))
|
||||
},
|
||||
|
||||
BoundKind::Expansion { original_call: _, bound_expanded } => {
|
||||
@@ -599,8 +601,8 @@ impl VM {
|
||||
}
|
||||
|
||||
fn flatten_value(val: Value, into: &mut Vec<Value>) {
|
||||
if let Value::List(l) = val {
|
||||
for item in l.iter() {
|
||||
if let Value::Tuple(t) = val {
|
||||
for item in t.values.iter() {
|
||||
Self::flatten_value(item.clone(), into);
|
||||
}
|
||||
} else {
|
||||
@@ -677,30 +679,15 @@ impl VM {
|
||||
Ok(())
|
||||
}
|
||||
BoundKind::Tuple { elements } => {
|
||||
// If the current value at offset is a List or Record, we dive into it.
|
||||
// If the current value at offset is a Tuple (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(());
|
||||
}
|
||||
_ => {}
|
||||
if let Some(Value::Tuple(t)) = values.get(*offset) {
|
||||
*offset += 1;
|
||||
let mut sub_offset = 0;
|
||||
for el in elements {
|
||||
self.unpack(el, &t.values, &mut sub_offset)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
for el in elements {
|
||||
|
||||
Reference in New Issue
Block a user