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:
@@ -1,4 +1,4 @@
|
||||
use std::collections::{HashMap, BTreeMap};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::any::{TypeId};
|
||||
use crate::ast::types::{Value, StaticType, Keyword, Signature};
|
||||
@@ -74,7 +74,7 @@ impl TypeRegistry {
|
||||
/// Helper to build the shadow record for an instance.
|
||||
/// This is used inside `Scriptable::wrap`.
|
||||
pub struct RecordBuilder {
|
||||
fields: HashMap<Keyword, Value>,
|
||||
fields: Vec<(Keyword, Value)>,
|
||||
}
|
||||
|
||||
impl Default for RecordBuilder {
|
||||
@@ -86,7 +86,7 @@ impl Default for RecordBuilder {
|
||||
impl RecordBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
fields: HashMap::new(),
|
||||
fields: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ impl RecordBuilder {
|
||||
where F: Fn(Vec<Value>) -> Value + 'static
|
||||
{
|
||||
let key = Keyword::intern(name);
|
||||
self.fields.insert(key, Value::Function(Rc::new(func)));
|
||||
self.fields.push((key, Value::Function(Rc::new(func))));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ impl RecordBuilder {
|
||||
|
||||
/// Helper to build the StaticType definition.
|
||||
pub struct TypeBuilder {
|
||||
fields: BTreeMap<Keyword, StaticType>,
|
||||
fields: Vec<(Keyword, StaticType)>,
|
||||
}
|
||||
|
||||
impl Default for TypeBuilder {
|
||||
@@ -130,14 +130,14 @@ impl Default for TypeBuilder {
|
||||
impl TypeBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
fields: BTreeMap::new(),
|
||||
fields: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn method(mut self, name: &str, params: Vec<StaticType>, ret: StaticType) -> Self {
|
||||
let key = Keyword::intern(name);
|
||||
let sig = StaticType::Function(Box::new(Signature { params: StaticType::Tuple(params), ret }));
|
||||
self.fields.insert(key, sig);
|
||||
self.fields.push((key, sig));
|
||||
self
|
||||
}
|
||||
|
||||
@@ -189,14 +189,14 @@ mod tests {
|
||||
// Check static type
|
||||
let st = TypeRegistry::resolve_type::<Person>(®istry);
|
||||
if let StaticType::Record(fields) = st {
|
||||
assert!(fields.contains_key(&Keyword::intern("greet")));
|
||||
assert!(fields.iter().any(|(k, _)| *k == Keyword::intern("greet")));
|
||||
} else {
|
||||
panic!("Expected Record type");
|
||||
}
|
||||
|
||||
// Check runtime behavior
|
||||
if let Value::Record(fields) = wrapped {
|
||||
let greet_fn = fields.get(&Keyword::intern("greet")).unwrap();
|
||||
let greet_fn = &fields.iter().find(|(k, _)| *k == Keyword::intern("greet")).unwrap().1;
|
||||
if let Value::Function(f) = greet_fn {
|
||||
let res = f(vec![]);
|
||||
if let Value::Text(s) = res {
|
||||
@@ -226,7 +226,7 @@ mod tests {
|
||||
if let Value::Function(f) = factory_val {
|
||||
let instance = f(vec![Value::Text("Bob".into()), Value::Int(40)]);
|
||||
if let Value::Record(fields) = instance {
|
||||
let greet_fn = fields.get(&Keyword::intern("greet")).unwrap();
|
||||
let greet_fn = &fields.iter().find(|(k, _)| *k == Keyword::intern("greet")).unwrap().1;
|
||||
if let Value::Function(gf) = greet_fn {
|
||||
let res = gf(vec![]);
|
||||
if let Value::Text(s) = res {
|
||||
|
||||
Reference in New Issue
Block a user