for a moment, everything works

This commit is contained in:
2025-02-21 23:53:31 +01:00
parent 9e7648bc72
commit cfa8b6ee52
23 changed files with 491 additions and 371 deletions

View File

@@ -23,7 +23,6 @@ orchid-api-traits = { version = "0.1.0", path = "../orchid-api-traits" }
ordered-float = "4.6.0"
regex = "1.11.1"
rust-embed = "8.5.0"
rust_decimal = "1.36.0"
some_executor = "0.4.0"
substack = "1.1.1"
test_executors = "0.3.2"

View File

@@ -98,7 +98,7 @@ impl Interned for String {
impl InternMarker for api::TStr {
type Interned = String;
async fn resolve(self, i: &Interner) -> Tok<Self::Interned> {
Tok::new(Rc::new(i.master.as_ref().unwrap().request(api::ExternStr(self)).await), self)
Tok::new(Rc::new(i.0.master.as_ref().unwrap().request(api::ExternStr(self)).await), self)
}
fn get_id(self) -> NonZeroU64 { self.0 }
fn from_id(id: NonZeroU64) -> Self { Self(id) }
@@ -125,7 +125,7 @@ impl Interned for Vec<Tok<String>> {
impl InternMarker for api::TStrv {
type Interned = Vec<Tok<String>>;
async fn resolve(self, i: &Interner) -> Tok<Self::Interned> {
let rep = i.master.as_ref().unwrap().request(api::ExternStrv(self)).await;
let rep = i.0.master.as_ref().unwrap().request(api::ExternStrv(self)).await;
let data = futures::future::join_all(rep.into_iter().map(|m| i.ex(m))).await;
Tok::new(Rc::new(data), self)
}
@@ -217,24 +217,26 @@ pub struct TypedInterners {
}
#[derive(Default)]
pub struct Interner {
pub struct InternerData {
interners: Mutex<TypedInterners>,
master: Option<Box<dyn DynRequester<Transfer = api::IntReq>>>,
}
#[derive(Clone, Default)]
pub struct Interner(Rc<InternerData>);
impl Interner {
pub fn new_master() -> Self { Self::default() }
pub fn new_replica(req: impl DynRequester<Transfer = api::IntReq> + 'static) -> Self {
Self { master: Some(Box::new(req)), interners: Mutex::default() }
Self(Rc::new(InternerData { master: Some(Box::new(req)), interners: Mutex::default() }))
}
/// Intern some data; query its identifier if not known locally
pub async fn i<T: Interned>(&self, t: &(impl Internable<Interned = T> + ?Sized)) -> Tok<T> {
let data = t.get_owned();
let mut g = self.interners.lock().await;
let mut g = self.0.interners.lock().await;
let typed = T::bimap(&mut g);
if let Some(tok) = typed.by_value(&data) {
return tok;
}
let marker = match &self.master {
let marker = match &self.0.master {
Some(c) => data.clone().intern(&**c).await,
None =>
T::Marker::from_id(NonZeroU64::new(ID.fetch_add(1, atomic::Ordering::Relaxed)).unwrap()),
@@ -245,29 +247,29 @@ impl Interner {
}
/// Extern an identifier; query the data it represents if not known locally
pub async fn ex<M: InternMarker>(&self, marker: M) -> Tok<M::Interned> {
if let Some(tok) = M::Interned::bimap(&mut *self.interners.lock().await).by_marker(marker) {
if let Some(tok) = M::Interned::bimap(&mut *self.0.interners.lock().await).by_marker(marker) {
return tok;
}
assert!(self.master.is_some(), "ID not in local interner and this is master");
assert!(self.0.master.is_some(), "ID not in local interner and this is master");
let token = marker.resolve(self).await;
M::Interned::bimap(&mut *self.interners.lock().await).insert(token.clone());
M::Interned::bimap(&mut *self.0.interners.lock().await).insert(token.clone());
token
}
pub async fn sweep_replica(&self) -> api::Retained {
assert!(self.master.is_some(), "Not a replica");
let mut g = self.interners.lock().await;
assert!(self.0.master.is_some(), "Not a replica");
let mut g = self.0.interners.lock().await;
api::Retained { strings: g.strings.sweep_replica(), vecs: g.vecs.sweep_replica() }
}
pub async fn sweep_master(&self, retained: api::Retained) {
assert!(self.master.is_none(), "Not master");
let mut g = self.interners.lock().await;
assert!(self.0.master.is_none(), "Not master");
let mut g = self.0.interners.lock().await;
g.strings.sweep_master(retained.strings.into_iter().collect());
g.vecs.sweep_master(retained.vecs.into_iter().collect());
}
}
impl fmt::Debug for Interner {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Interner{{ replica: {} }}", self.master.is_none())
write!(f, "Interner{{ replica: {} }}", self.0.master.is_none())
}
}

View File

@@ -1,9 +1,7 @@
use std::num::IntErrorKind;
use std::ops::Range;
use num_traits::ToPrimitive;
use ordered_float::NotNan;
use rust_decimal::Decimal;
use crate::error::{OrcErr, mk_err};
use crate::interner::Interner;
@@ -12,24 +10,17 @@ use crate::location::Pos;
/// A number, either floating point or unsigned int, parsed by Orchid.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Numeric {
/// A nonnegative integer
Uint(u64),
/// An integer
Int(i64),
/// A binary float other than NaN
Float(NotNan<f64>),
/// A decimal number
Decimal(Decimal),
}
impl Numeric {
pub fn decimal(num: i64, scale: u32) -> Self { Self::Decimal(Decimal::new(num, scale)) }
pub fn float(value: f64) -> Self { Self::Float(NotNan::new(value).unwrap()) }
pub fn to_f64(self) -> NotNan<f64> {
match self {
Self::Float(f) => f,
Self::Decimal(d) => {
let f = d.to_f64().expect("This is apparently always possible");
NotNan::new(f).expect("decimal was nan")
},
Self::Uint(i) => NotNan::new(i as f64).expect("int cannot be NaN"),
Self::Int(i) => NotNan::new(i as f64).expect("int cannot be NaN"),
}
}
}
@@ -77,31 +68,31 @@ pub async fn num_to_err(NumError { kind, range }: NumError, offset: u32, i: &Int
/// Parse a numbre literal out of text
pub fn parse_num(string: &str) -> Result<Numeric, NumError> {
let overflow_err = NumError { range: 0..string.len(), kind: NumErrorKind::Overflow };
let overflow_e = NumError { range: 0..string.len(), kind: NumErrorKind::Overflow };
let (radix, noprefix, pos) = (string.strip_prefix("0x").map(|s| (16u8, s, 2)))
.or_else(|| string.strip_prefix("0b").map(|s| (2u8, s, 2)))
.or_else(|| string.strip_prefix("0o").map(|s| (8u8, s, 2)))
.unwrap_or((10u8, string, 0));
eprintln!("({radix}, {noprefix}, {pos})");
// identity
let (base, exponent) = match noprefix.split_once('p') {
let (base_s, exponent) = match noprefix.split_once('p') {
Some((b, e)) => {
let (s, d, len) = e.strip_prefix('-').map_or((1, e, 0), |ue| (-1, ue, 1));
(b, s * int_parse(d, 10, pos + b.len() + 1 + len)? as i32)
},
None => (noprefix, 0),
};
eprintln!("({base},{exponent})");
match base.split_once('.') {
eprintln!("({base_s},{exponent})");
match base_s.split_once('.') {
None => {
let base_usize = int_parse(base, radix, pos)?;
let base = int_parse(base_s, radix, pos)?;
if let Ok(pos_exp) = u32::try_from(exponent) {
if let Some(radical) = u64::from(radix).checked_pow(pos_exp) {
let number = base_usize.checked_mul(radical).ok_or(overflow_err)?;
return Ok(Numeric::Uint(number));
let num = base.checked_mul(radical).and_then(|m| m.try_into().ok()).ok_or(overflow_e)?;
return Ok(Numeric::Int(num));
}
}
let f = (base_usize as f64) * (radix as f64).powi(exponent);
let f = (base as f64) * (radix as f64).powi(exponent);
let err = NumError { range: 0..string.len(), kind: NumErrorKind::NaN };
Ok(Numeric::Float(NotNan::new(f).map_err(|_| err)?))
},
@@ -109,25 +100,9 @@ pub fn parse_num(string: &str) -> Result<Numeric, NumError> {
let whole_n = int_parse(whole, radix, pos)?;
let part_n = int_parse(part, radix, pos + whole.len() + 1)?;
let scale = part.chars().filter(|c| *c != '_').count() as u32;
if radix == 10 {
let scaled_unit = 10u64.checked_pow(scale).ok_or(overflow_err.clone())?;
let scaled_n = i128::from(whole_n) * i128::from(scaled_unit) + i128::from(part_n);
let decimal = Decimal::from_i128_with_scale(scaled_n, scale);
let p = if let Ok(uexp) = u32::try_from(exponent) {
let e_multiplier = 10i64.checked_pow(uexp).ok_or(overflow_err)?;
Decimal::new(e_multiplier, 0)
} else {
let inv_oom = u32::try_from(-exponent).map_err(|_| overflow_err)?;
eprintln!("inv_oom: {inv_oom}");
Decimal::new(1, inv_oom)
};
eprintln!("({scaled_n}, {scale}, {p})");
Ok(Numeric::Decimal(decimal * p))
} else {
let real_val = whole_n as f64 + (part_n as f64 / (radix as f64).powi(scale as i32));
let f = real_val * (radix as f64).powi(exponent);
Ok(Numeric::Float(NotNan::new(f).expect("None of the inputs are NaN")))
}
let real_val = whole_n as f64 + (part_n as f64 / (radix as f64).powi(scale as i32));
let f = real_val * (radix as f64).powi(exponent);
Ok(Numeric::Float(NotNan::new(f).expect("None of the inputs are NaN")))
},
}
}
@@ -168,7 +143,7 @@ mod test {
#[test]
fn just_ints() {
let test = |s, n| assert_eq!(parse_num(s), Ok(Numeric::Uint(n)));
let test = |s, n| assert_eq!(parse_num(s), Ok(Numeric::Int(n)));
test("12345", 12345);
test("0xcafebabe", 0xcafebabe);
test("0o751", 0o751);
@@ -178,11 +153,11 @@ mod test {
#[test]
fn decimals() {
let test = |s, n| assert_eq!(parse_num(s), Ok(n));
test("3.1417", Numeric::decimal(31417, 4));
test("3.1417", Numeric::float(3.1417));
test("0xf.cafe", Numeric::float(0xf as f64 + 0xcafe as f64 / 0x10000 as f64));
test("34p3", Numeric::Uint(34000));
test("0x2p3", Numeric::Uint(0x2 * 0x1000));
test("1.5p3", Numeric::decimal(1500, 0));
test("34p3", Numeric::Int(34000));
test("0x2p3", Numeric::Int(0x2 * 0x1000));
test("1.5p3", Numeric::float(1500.0));
test("0x2.5p3", Numeric::float((0x25 * 0x100) as f64));
}
}