More basics
This commit is contained in:
parent
c93fea0545
commit
e7f559c944
|
@ -1,94 +1,25 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
|
|
||||||
/// Single-precision IEEE 754 Value
|
pub fn cmp_f32(a: f32, b: f32) -> Ordering {
|
||||||
#[derive(Clone, Copy, Debug)]
|
let mut a: u32 = a.to_bits();
|
||||||
pub struct Float(pub f32);
|
let mut b: u32 = b.to_bits();
|
||||||
|
if a & 0x8000_0000 != 0 { a ^= 0x7fff_ffff; }
|
||||||
/// Double-precision IEEE 754 Value
|
if b & 0x8000_0000 != 0 { b ^= 0x7fff_ffff; }
|
||||||
#[derive(Clone, Copy, Debug)]
|
(a as i32).cmp(&(b as i32))
|
||||||
pub struct Double(pub f64);
|
|
||||||
|
|
||||||
impl From<f32> for Float {
|
|
||||||
fn from(v: f32) -> Self {
|
|
||||||
Float(v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Float> for f32 {
|
pub fn eq_f32(a: f32, b: f32) -> bool {
|
||||||
fn from(v: Float) -> Self {
|
a.to_bits() == b.to_bits()
|
||||||
v.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hash for Float {
|
pub fn cmp_f64(a: f64, b: f64) -> Ordering {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
let mut a: u64 = a.to_bits();
|
||||||
self.0.to_bits().hash(state);
|
let mut b: u64 = b.to_bits();
|
||||||
}
|
if a & 0x8000_0000_0000_0000 != 0 { a ^= 0x7fff_ffff_ffff_ffff; }
|
||||||
|
if b & 0x8000_0000_0000_0000 != 0 { b ^= 0x7fff_ffff_ffff_ffff; }
|
||||||
|
(a as i64).cmp(&(b as i64))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Float {
|
pub fn eq_f64(a: f64, b: f64) -> bool {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
a.to_bits() == b.to_bits()
|
||||||
self.0.to_bits() == other.0.to_bits()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ord for Float {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
let mut a: u32 = self.0.to_bits();
|
|
||||||
let mut b: u32 = other.0.to_bits();
|
|
||||||
if a & 0x8000_0000 != 0 { a ^= 0x7fff_ffff; }
|
|
||||||
if b & 0x8000_0000 != 0 { b ^= 0x7fff_ffff; }
|
|
||||||
(a as i32).cmp(&(b as i32))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for Float {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for Float {}
|
|
||||||
|
|
||||||
impl From<f64> for Double {
|
|
||||||
fn from(v: f64) -> Self {
|
|
||||||
Double(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Double> for f64 {
|
|
||||||
fn from(v: Double) -> Self {
|
|
||||||
v.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hash for Double {
|
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
||||||
self.0.to_bits().hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq for Double {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.0.to_bits() == other.0.to_bits()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Ord for Double {
|
|
||||||
fn cmp(&self, other: &Self) -> Ordering {
|
|
||||||
let mut a: u64 = self.0.to_bits();
|
|
||||||
let mut b: u64 = other.0.to_bits();
|
|
||||||
if a & 0x8000_0000_0000_0000 != 0 { a ^= 0x7fff_ffff_ffff_ffff; }
|
|
||||||
if b & 0x8000_0000_0000_0000 != 0 { b ^= 0x7fff_ffff_ffff_ffff; }
|
|
||||||
(a as i64).cmp(&(b as i64))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialOrd for Double {
|
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
|
||||||
Some(self.cmp(other))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for Double {}
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use bytemuck::TransparentWrapper;
|
use bytemuck::TransparentWrapper;
|
||||||
|
use float::{eq_f32, eq_f64, cmp_f32, cmp_f64};
|
||||||
|
|
||||||
use std::borrow::{Cow, Borrow};
|
use std::borrow::{Cow, Borrow};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
@ -12,8 +13,6 @@ pub use std::collections::BTreeMap as Map;
|
||||||
pub mod float;
|
pub mod float;
|
||||||
pub mod signed_integer;
|
pub mod signed_integer;
|
||||||
|
|
||||||
pub use float::Float;
|
|
||||||
pub use float::Double;
|
|
||||||
pub use signed_integer::SignedInteger;
|
pub use signed_integer::SignedInteger;
|
||||||
|
|
||||||
/// The kinds of `Value` from the specification.
|
/// The kinds of `Value` from the specification.
|
||||||
|
@ -205,9 +204,9 @@ impl<'a, D: Domain> PartialEq for dyn Value<D> + 'a {
|
||||||
AtomClass::Boolean =>
|
AtomClass::Boolean =>
|
||||||
self.as_boolean().unwrap() == other.as_boolean().unwrap(),
|
self.as_boolean().unwrap() == other.as_boolean().unwrap(),
|
||||||
AtomClass::Float =>
|
AtomClass::Float =>
|
||||||
Float(self.as_float().unwrap()) == Float(other.as_float().unwrap()),
|
eq_f32(self.as_float().unwrap(), other.as_float().unwrap()),
|
||||||
AtomClass::Double =>
|
AtomClass::Double =>
|
||||||
Double(self.as_double().unwrap()) == Double(other.as_double().unwrap()),
|
eq_f64(self.as_double().unwrap(), other.as_double().unwrap()),
|
||||||
AtomClass::SignedInteger =>
|
AtomClass::SignedInteger =>
|
||||||
self.as_signed_integer().unwrap() == other.as_signed_integer().unwrap(),
|
self.as_signed_integer().unwrap() == other.as_signed_integer().unwrap(),
|
||||||
AtomClass::String =>
|
AtomClass::String =>
|
||||||
|
@ -270,9 +269,9 @@ impl<'a, D: Domain> Ord for dyn Value<D> + 'a {
|
||||||
AtomClass::Boolean =>
|
AtomClass::Boolean =>
|
||||||
self.as_boolean().cmp(&other.as_boolean()),
|
self.as_boolean().cmp(&other.as_boolean()),
|
||||||
AtomClass::Float =>
|
AtomClass::Float =>
|
||||||
Float(self.as_float().unwrap()).cmp(&Float(other.as_float().unwrap())),
|
cmp_f32(self.as_float().unwrap(), other.as_float().unwrap()),
|
||||||
AtomClass::Double =>
|
AtomClass::Double =>
|
||||||
Double(self.as_double().unwrap()).cmp(&Double(other.as_double().unwrap())),
|
cmp_f64(self.as_double().unwrap(), other.as_double().unwrap()),
|
||||||
AtomClass::SignedInteger =>
|
AtomClass::SignedInteger =>
|
||||||
self.as_signed_integer().cmp(&other.as_signed_integer()),
|
self.as_signed_integer().cmp(&other.as_signed_integer()),
|
||||||
AtomClass::String =>
|
AtomClass::String =>
|
||||||
|
@ -332,10 +331,16 @@ impl<D: Domain> Value<D> for u64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Domain> Value<D> for Float {
|
impl<D: Domain> Value<D> for f32 {
|
||||||
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) }
|
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) }
|
||||||
fn as_float(&self) -> Option<f32> { Some(self.0) }
|
fn as_float(&self) -> Option<f32> { Some(*self) }
|
||||||
fn as_double(&self) -> Option<f64> { Some(self.0 as f64) }
|
fn as_double(&self) -> Option<f64> { Some(*self as f64) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Domain> Value<D> for f64 {
|
||||||
|
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) }
|
||||||
|
fn as_float(&self) -> Option<f32> { Some(*self as f32) }
|
||||||
|
fn as_double(&self) -> Option<f64> { Some(*self) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: Domain> Value<D> for str {
|
impl<D: Domain> Value<D> for str {
|
||||||
|
@ -348,6 +353,46 @@ impl<D: Domain> Value<D> for String {
|
||||||
fn as_string(&self) -> Option<Cow<'_, str>> { Some(Cow::Borrowed(self)) }
|
fn as_string(&self) -> Option<Cow<'_, str>> { Some(Cow::Borrowed(self)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Bytes<T: AsRef<[u8]>>(T);
|
||||||
|
|
||||||
|
impl<T: AsRef<[u8]> + Debug, D: Domain> Value<D> for Bytes<T> {
|
||||||
|
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::ByteString) }
|
||||||
|
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> { Some(Cow::Borrowed(self.0.as_ref())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Symbol<T: AsRef<str> + Debug>(T);
|
||||||
|
|
||||||
|
impl<T: AsRef<str> + Debug, D: Domain> Value<D> for Symbol<T> {
|
||||||
|
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Symbol) }
|
||||||
|
fn as_symbol(&self) -> Option<Cow<'_, str>> { Some(Cow::Borrowed(self.0.as_ref())) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct Record<V>(Vec<V> /* at least one element, for the label */);
|
||||||
|
|
||||||
|
impl<V> Record<V> {
|
||||||
|
pub fn new(label: V, mut fields: Vec<V>) -> Self {
|
||||||
|
fields.insert(0, label);
|
||||||
|
Record(fields)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<D: Domain, V: Value<D>> Value<D> for Record<V> {
|
||||||
|
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Record) }
|
||||||
|
fn is_record(&self) -> bool { true }
|
||||||
|
fn label(&self) -> &dyn Value<D> { &self.0[0] }
|
||||||
|
fn len(&self) -> usize { self.0.len() - 1 }
|
||||||
|
fn index(&self, i: usize) -> &dyn Value<D> { &self.0[i + 1] }
|
||||||
|
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> {
|
||||||
|
Box::new(self.0[1..].iter().map(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<D: Domain, V: Value<D>> Value<D> for Vec<V> {
|
impl<D: Domain, V: Value<D>> Value<D> for Vec<V> {
|
||||||
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) }
|
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) }
|
||||||
fn is_sequence(&self) -> bool { true }
|
fn is_sequence(&self) -> bool { true }
|
||||||
|
@ -410,32 +455,13 @@ impl<D: Domain, V: Value<D>> Value<D> for Map<Box<dyn Value<D>>, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct Record<V>(Vec<V> /* at least one element, for the label */);
|
#[repr(transparent)]
|
||||||
|
pub struct Embedded<D: Domain>(D);
|
||||||
|
|
||||||
impl<V> Record<V> {
|
impl<D: Domain> Value<D> for Embedded<D> {
|
||||||
pub fn new(label: V, mut fields: Vec<V>) -> Self {
|
fn value_class(&self) -> ValueClass { ValueClass::Embedded }
|
||||||
fields.insert(0, label);
|
fn is_embedded(&self) -> bool { true }
|
||||||
Record(fields)
|
fn embedded(&self) -> Cow<'_, D> { Cow::Borrowed(&self.0) }
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<D: Domain, V: Value<D>> Value<D> for Record<V> {
|
|
||||||
fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Record) }
|
|
||||||
fn is_record(&self) -> bool { true }
|
|
||||||
fn label(&self) -> &dyn Value<D> { &self.0[0] }
|
|
||||||
fn len(&self) -> usize { self.0.len() - 1 }
|
|
||||||
fn index(&self, i: usize) -> &dyn Value<D> { &self.0[i + 1] }
|
|
||||||
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Value<D>> + '_> {
|
|
||||||
Box::new(self.0[1..].iter().map(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
|
||||||
pub struct Symbol<T: AsRef<str> + Debug>(T);
|
|
||||||
|
|
||||||
impl<T: AsRef<str> + Debug, D: Domain> Value<D> for Symbol<T> {
|
|
||||||
fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Symbol) }
|
|
||||||
fn as_symbol(&self) -> Option<Cow<'_, str>> { Some(Cow::Borrowed(self.0.as_ref())) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
Loading…
Reference in New Issue