From c93fea05459d02721690ab4df39e7e224a0dd31a Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Wed, 2 Nov 2022 17:03:38 +0100 Subject: [PATCH] More --- implementations/rust/oo/src/lib.rs | 224 ++++++++++++++++++----------- 1 file changed, 142 insertions(+), 82 deletions(-) diff --git a/implementations/rust/oo/src/lib.rs b/implementations/rust/oo/src/lib.rs index 018d9d5..d4fa4e1 100644 --- a/implementations/rust/oo/src/lib.rs +++ b/implementations/rust/oo/src/lib.rs @@ -58,29 +58,29 @@ pub trait Value: Debug { fn as_double(&self) -> Option { None } fn is_signed_integer(&self) -> bool { false } - fn as_signed_integer(&self) -> Option> { None } + fn as_signed_integer(&self) -> Option { None } fn as_string(&self) -> Option> { None } fn as_bytestring(&self) -> Option> { None } fn as_symbol(&self) -> Option> { None } fn is_record(&self) -> bool { false } - fn label(&self) -> Option<&dyn Value> { None } + fn label(&self) -> &dyn Value { panic!("Not a record") } fn is_sequence(&self) -> bool { false } - fn len(&self) -> Option { None } - fn index(&self, _i: usize) -> &dyn Value { panic!("Not a sequence") } - fn iter(&self) -> Option> + '_>> { None } + fn len(&self) -> usize { panic!("Has no length") } + fn index(&self, _i: usize) -> &dyn Value { panic!("Not indexable") } + fn iter(&self) -> Box> + '_> { panic!("Not iterable") } fn is_set(&self) -> bool { false } fn has(&self, _v: &dyn Value) -> bool { false } fn is_dictionary(&self) -> bool { false } fn get(&self, _k: &dyn Value) -> Option<&dyn Value> { None } - fn entries(&self) -> Option, &dyn Value)> + '_>> { None } + fn entries(&self) -> Box, &dyn Value)> + '_> { panic!("Not a dictionary") } fn is_embedded(&self) -> bool { false } - fn embedded(&self) -> Option> { None } + fn embedded(&self) -> Cow<'_, D> { panic!("Not an embedded value") } fn annotations(&self) -> Option<&[Box>]> { None } } @@ -89,28 +89,33 @@ pub fn value>(v: &V) -> &dyn Value { v } +pub fn owned + 'static>(v: V) -> Box> { + Box::new(v) +} + impl<'a, D: Domain, V: Value + ?Sized> Value for &'a V { fn value_class(&self) -> ValueClass { (*self).value_class() } fn as_boolean(&self) -> Option { (*self).as_boolean() } fn as_float(&self) -> Option { (*self).as_float() } fn as_double(&self) -> Option { (*self).as_double() } fn is_signed_integer(&self) -> bool { (*self).is_signed_integer() } - fn as_signed_integer(&self) -> Option> { (*self).as_signed_integer() } + fn as_signed_integer(&self) -> Option { (*self).as_signed_integer() } fn as_string(&self) -> Option> { (*self).as_string() } fn as_bytestring(&self) -> Option> { (*self).as_bytestring() } fn as_symbol(&self) -> Option> { (*self).as_symbol() } fn is_record(&self) -> bool { (*self).is_record() } - fn label(&self) -> Option<&dyn Value> { (*self).label() } + fn label(&self) -> &dyn Value { (*self).label() } fn is_sequence(&self) -> bool { (*self).is_sequence() } - fn len(&self) -> Option { (*self).len() } + fn len(&self) -> usize { (*self).len() } fn index(&self, i: usize) -> &dyn Value { (*self).index(i) } + fn iter(&self) -> Box> + '_> { (*self).iter() } fn is_set(&self) -> bool { (*self).is_set() } fn has(&self, v: &dyn Value) -> bool { (*self).has(v) } fn is_dictionary(&self) -> bool { (*self).is_dictionary() } fn get(&self, k: &dyn Value) -> Option<&dyn Value> { (*self).get(k) } - fn entries(&self) -> Option, &dyn Value)> + '_>> { (*self).entries() } + fn entries(&self) -> Box, &dyn Value)> + '_> { (*self).entries() } fn is_embedded(&self) -> bool { (*self).is_embedded() } - fn embedded(&self) -> Option> { (*self).embedded() } + fn embedded(&self) -> Cow<'_, D> { (*self).embedded() } fn annotations(&self) -> Option<&[Box>]> { (*self).annotations() } } @@ -120,22 +125,23 @@ impl Value for Box> { fn as_float(&self) -> Option { self.as_ref().as_float() } fn as_double(&self) -> Option { self.as_ref().as_double() } fn is_signed_integer(&self) -> bool { self.as_ref().is_signed_integer() } - fn as_signed_integer(&self) -> Option> { self.as_ref().as_signed_integer() } + fn as_signed_integer(&self) -> Option { self.as_ref().as_signed_integer() } fn as_string(&self) -> Option> { self.as_ref().as_string() } fn as_bytestring(&self) -> Option> { self.as_ref().as_bytestring() } fn as_symbol(&self) -> Option> { self.as_ref().as_symbol() } fn is_record(&self) -> bool { self.as_ref().is_record() } - fn label(&self) -> Option<&dyn Value> { self.as_ref().label() } + fn label(&self) -> &dyn Value { self.as_ref().label() } fn is_sequence(&self) -> bool { self.as_ref().is_sequence() } - fn len(&self) -> Option { self.as_ref().len() } + fn len(&self) -> usize { self.as_ref().len() } fn index(&self, i: usize) -> &dyn Value { self.as_ref().index(i) } + fn iter(&self) -> Box> + '_> { self.as_ref().iter() } fn is_set(&self) -> bool { self.as_ref().is_set() } fn has(&self, v: &dyn Value) -> bool { self.as_ref().has(v) } fn is_dictionary(&self) -> bool { self.as_ref().is_dictionary() } fn get(&self, k: &dyn Value) -> Option<&dyn Value> { self.as_ref().get(k) } - fn entries(&self) -> Option, &dyn Value)> + '_>> { self.as_ref().entries() } + fn entries(&self) -> Box, &dyn Value)> + '_> { self.as_ref().entries() } fn is_embedded(&self) -> bool { self.as_ref().is_embedded() } - fn embedded(&self) -> Option> { self.as_ref().embedded() } + fn embedded(&self) -> Cow<'_, D> { self.as_ref().embedded() } fn annotations(&self) -> Option<&[Box>]> { self.as_ref().annotations() } } @@ -154,23 +160,23 @@ impl<'a, D: Domain> Hash for dyn Value + 'a { ValueClass::Compound(c) => match c { CompoundClass::Sequence | CompoundClass::Set => { - state.write_usize(self.len().unwrap()); - for v in self.iter().unwrap() { v.hash(state) } + state.write_usize(self.len()); + for v in self.iter() { v.hash(state) } } CompoundClass::Record => { - self.label().unwrap().hash(state); - state.write_usize(self.len().unwrap()); - for v in self.iter().unwrap() { v.hash(state) } + self.label().hash(state); + state.write_usize(self.len()); + for v in self.iter() { v.hash(state) } } CompoundClass::Dictionary => { - state.write_usize(self.len().unwrap()); - for (k, v) in self.entries().unwrap() { + state.write_usize(self.len()); + for (k, v) in self.entries() { k.hash(state); v.hash(state); } } } - ValueClass::Embedded => self.embedded().unwrap().hash(state), + ValueClass::Embedded => self.embedded().hash(state), } } } @@ -213,24 +219,45 @@ impl<'a, D: Domain> PartialEq for dyn Value + 'a { } ValueClass::Compound(c) => match c { CompoundClass::Record => { - if self.label().unwrap() != other.label().unwrap() { return false; } - iters_eq(self.iter().unwrap(), other.iter().unwrap()) + if self.label() != other.label() { return false; } + iters_eq(self.iter(), other.iter()) } CompoundClass::Sequence => { - iters_eq(self.iter().unwrap(), other.iter().unwrap()) + iters_eq(self.iter(), other.iter()) } CompoundClass::Set => { - let s1 = self.iter().unwrap().collect::>(); - let s2 = other.iter().unwrap().collect::>(); + let s1 = self.iter().collect::>(); + let s2 = other.iter().collect::>(); s1 == s2 } CompoundClass::Dictionary => { - let d1 = self.entries().unwrap().collect::>(); - let d2 = other.entries().unwrap().collect::>(); + let d1 = self.entries().collect::>(); + let d2 = other.entries().collect::>(); d1 == d2 } } - ValueClass::Embedded => self.embedded().unwrap() == other.embedded().unwrap(), + ValueClass::Embedded => self.embedded() == other.embedded(), + } + } +} + +fn iters_cmp<'a, D: Domain>( + mut i1: Box> + 'a>, + mut i2: Box> + 'a>, +) -> Ordering { + loop { + match i1.next() { + None => match i2.next() { + None => return Ordering::Equal, + Some(_) => return Ordering::Less, + } + Some(v1) => match i2.next() { + None => return Ordering::Greater, + Some(v2) => match v1.cmp(v2) { + Ordering::Equal => (), + other => return other, + } + } } } } @@ -238,33 +265,41 @@ impl<'a, D: Domain> PartialEq for dyn Value + 'a { impl<'a, D: Domain> Ord for dyn Value + 'a { fn cmp(&self, other: &Self) -> Ordering { let cls = self.value_class(); - match cls.cmp(&other.value_class()) { - Ordering::Less => Ordering::Less, - Ordering::Greater => Ordering::Greater, - Ordering::Equal => match cls { - ValueClass::Atomic(a) => match a { - AtomClass::Boolean => - self.as_boolean().cmp(&other.as_boolean()), - AtomClass::Float => - Float(self.as_float().unwrap()).cmp(&Float(other.as_float().unwrap())), - AtomClass::Double => - Double(self.as_double().unwrap()).cmp(&Double(other.as_double().unwrap())), - AtomClass::SignedInteger => - self.as_signed_integer().cmp(&other.as_signed_integer()), - AtomClass::String => - self.as_string().cmp(&other.as_string()), - AtomClass::ByteString => - self.as_bytestring().cmp(&other.as_bytestring()), - AtomClass::Symbol => - self.as_symbol().cmp(&other.as_symbol()), - }, - ValueClass::Compound(c) => match c { - _ => todo!(), - }, - ValueClass::Embedded => - self.embedded().cmp(&other.embedded()), - } - } + cls.cmp(&other.value_class()).then_with(|| match cls { + ValueClass::Atomic(a) => match a { + AtomClass::Boolean => + self.as_boolean().cmp(&other.as_boolean()), + AtomClass::Float => + Float(self.as_float().unwrap()).cmp(&Float(other.as_float().unwrap())), + AtomClass::Double => + Double(self.as_double().unwrap()).cmp(&Double(other.as_double().unwrap())), + AtomClass::SignedInteger => + self.as_signed_integer().cmp(&other.as_signed_integer()), + AtomClass::String => + self.as_string().cmp(&other.as_string()), + AtomClass::ByteString => + self.as_bytestring().cmp(&other.as_bytestring()), + AtomClass::Symbol => + self.as_symbol().cmp(&other.as_symbol()), + }, + ValueClass::Compound(c) => match c { + CompoundClass::Record => + self.label().cmp(other.label()).then_with( + || iters_cmp(self.iter(), other.iter())), + CompoundClass::Sequence => iters_cmp(self.iter(), other.iter()), + CompoundClass::Set => { + let s1 = self.iter().collect::>(); + let s2 = other.iter().collect::>(); + s1.cmp(&s2) + } + CompoundClass::Dictionary => { + let d1 = self.entries().collect::>(); + let d2 = other.entries().collect::>(); + d1.cmp(&d2) + } + }, + ValueClass::Embedded => self.embedded().cmp(&other.embedded()), + }) } } @@ -292,8 +327,8 @@ impl Value for bool { impl Value for u64 { fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::SignedInteger) } - fn as_signed_integer(&self) -> Option> { - Some(Cow::Owned((*self).into())) + fn as_signed_integer(&self) -> Option { + Some((*self).into()) } } @@ -316,30 +351,30 @@ impl Value for String { impl> Value for Vec { fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) } fn is_sequence(&self) -> bool { true } - fn len(&self) -> Option { Some(self.len()) } + fn len(&self) -> usize { self.len() } fn index(&self, i: usize) -> &dyn Value { &self[i] } - fn iter(&self) -> Option> + '_>> { - Some(Box::new(self[..].iter().map(value))) + fn iter(&self) -> Box> + '_> { + Box::new(self[..].iter().map(value)) } } impl> Value for [V] { fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) } fn is_sequence(&self) -> bool { true } - fn len(&self) -> Option { Some(self.len()) } + fn len(&self) -> usize { self.len() } fn index(&self, i: usize) -> &dyn Value { &self[i] } - fn iter(&self) -> Option> + '_>> { - Some(Box::new(self[..].iter().map(value))) + fn iter(&self) -> Box> + '_> { + Box::new(self[..].iter().map(value)) } } impl Value for Set>> { fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Set) } fn is_set(&self) -> bool { true } - fn len(&self) -> Option { Some(self.len()) } + fn len(&self) -> usize { self.len() } fn has(&self, v: &dyn Value) -> bool { self.contains(v) } - fn iter(&self) -> Option> + '_>> { - Some(Box::new(self.iter().map(value))) + fn iter(&self) -> Box> + '_> { + Box::new(self.iter().map(value)) } } @@ -361,7 +396,7 @@ impl<'a, 'b: 'a, D: Domain> Borrow> for Box + 'b> { impl> Value for Map>, V> { fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Dictionary) } fn is_dictionary(&self) -> bool { true } - fn len(&self) -> Option { Some(self.len()) } + fn len(&self) -> usize { self.len() } fn has(&self, v: &dyn Value) -> bool { self.contains_key(v) } fn get(&self, k: &dyn Value) -> Option<&dyn Value> { match Map::get(self, Key::wrap_ref(&k)) { @@ -369,20 +404,38 @@ impl> Value for Map>, V> { None => None, } } - fn entries(&self) -> Option, &dyn Value)> + '_>> { - Some(Box::new(self.iter().map(|(k,v)| (value(k), value(v))))) + fn entries(&self) -> Box, &dyn Value)> + '_> { + Box::new(self.iter().map(|(k,v)| (value(k), value(v)))) } } #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Record(Vec /* at least one element, for the label */); +impl Record { + pub fn new(label: V, mut fields: Vec) -> Self { + fields.insert(0, label); + Record(fields) + } +} + impl> Value for Record { fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Record) } fn is_record(&self) -> bool { true } - fn label(&self) -> Option<&dyn Value> { Some(&self.0[0]) } - fn len(&self) -> Option { Some(self.0.len() - 1) } + fn label(&self) -> &dyn Value { &self.0[0] } + fn len(&self) -> usize { self.0.len() - 1 } fn index(&self, i: usize) -> &dyn Value { &self.0[i + 1] } + fn iter(&self) -> Box> + '_> { + Box::new(self.0[1..].iter().map(value)) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub struct Symbol + Debug>(T); + +impl + Debug, D: Domain> Value for Symbol { + fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Symbol) } + fn as_symbol(&self) -> Option> { Some(Cow::Borrowed(self.0.as_ref())) } } #[derive(Debug)] @@ -400,22 +453,23 @@ impl> Value for Annotations { fn as_float(&self) -> Option { self.value().as_float() } fn as_double(&self) -> Option { self.value().as_double() } fn is_signed_integer(&self) -> bool { self.value().is_signed_integer() } - fn as_signed_integer(&self) -> Option> { self.value().as_signed_integer() } + fn as_signed_integer(&self) -> Option { self.value().as_signed_integer() } fn as_string(&self) -> Option> { self.value().as_string() } fn as_bytestring(&self) -> Option> { self.value().as_bytestring() } fn as_symbol(&self) -> Option> { self.value().as_symbol() } fn is_record(&self) -> bool { self.value().is_record() } - fn label(&self) -> Option<&dyn Value> { self.value().label() } + fn label(&self) -> &dyn Value { self.value().label() } fn is_sequence(&self) -> bool { self.value().is_sequence() } - fn len(&self) -> Option { self.value().len() } + fn len(&self) -> usize { self.value().len() } fn index(&self, i: usize) -> &dyn Value { self.value().index(i) } + fn iter(&self) -> Box> + '_> { self.value().iter() } fn is_set(&self) -> bool { self.value().is_set() } fn has(&self, v: &dyn Value) -> bool { self.value().has(v) } fn is_dictionary(&self) -> bool { self.value().is_dictionary() } fn get(&self, k: &dyn Value) -> Option<&dyn Value> { self.value().get(k) } - fn entries(&self) -> Option, &dyn Value)> + '_>> { self.value().entries() } + fn entries(&self) -> Box, &dyn Value)> + '_> { self.value().entries() } fn is_embedded(&self) -> bool { self.value().is_embedded() } - fn embedded(&self) -> Option> { self.value().embedded() } + fn embedded(&self) -> Cow<'_, D> { self.value().embedded() } fn annotations(&self) -> Option<&[Box>]> { Some(&self.1) } } @@ -454,10 +508,16 @@ mod demo { } #[test] fn a() { + let l = Symbol("label"); + let r = Record::new(owned::(l.clone()), vec![owned(1), owned(2), owned(3)]); + let r2 = Record::new(owned::(l), vec![owned(1), owned(2), owned(4)]); + let mut v: Map>, String> = Map::new(); v.insert(Box::new("abc"), "def".to_owned()); v.insert(Box::new(123), "xyz".to_owned()); v.insert(Box::new(vec![1, 2, 3]), "www".to_owned()); + v.insert(Box::new(r2), "bbb".to_owned()); + v.insert(Box::new(r), "aaa".to_owned()); let w: &dyn Value = &v; println!("GETw abc {:?}", w.get(&"abc")); println!("GETw 123 {:?}", w.get(&123)); @@ -465,7 +525,7 @@ mod demo { println!("GETv abc {:?}", v.get(value(&"abc"))); println!("GETv 123 {:?}", v.get(value(&123))); println!("GETv qqq {:?}", v.get(value(&"qqq"))); - for (kk, vv) in w.entries().unwrap() { + for (kk, vv) in w.entries() { println!("{:?} {:?} ==> {:?} {:?}", kk.value_class(), kk, vv.value_class(), vv); }