use std::sync::{Arc, RwLock}; use std::collections::BTreeMap; pub use clojure_reader::edn::Edn; //#[derive(Debug, Copy, Clone, Default, PartialEq)] //pub struct Items<'a>(&'a [Item<'a>]); //impl<'a> Items<'a> { //fn iter (&'a self) -> ItemsIterator<'a> { //ItemsIterator(0, self.0) //} //} //pub struct ItemsIterator<'a>(usize, &'a [Item<'a>]); //impl<'a> Iterator for ItemsIterator<'a> { //type Item = &'a Item<'a>; //fn next (&mut self) -> Option { //let item = self.1.get(self.0); //self.0 += 1; //item //} //} /* nice but doesn't work without compile time slice concat (which i guess could be implemeted using an unsafe linked list?) never done that one before im ny life, might try use konst::slice_concat; const fn read <'a> ( chars: impl Iterator ) -> Result, ParseError> { use Range::*; let mut state = Range::Nil; let mut tokens: &[Range<'a>] = &[]; while let Some(c) = chars.next() { state = match state { // must begin expression Nil => match c { ' ' => Nil, '(' => Exp(&[]), ':' => Sym(&[]), '1'..'9' => Num(digit(c)), 'a'..'z' => Key(&[&[c]]), _ => return Err(ParseError::Unexpected(c)) }, Num(b) => match c { ' ' => return Ok(Num(digit(c))), '1'..'9' => Num(b*10+digit(c)), _ => return Err(ParseError::Unexpected(c)) } Sym([]) => match c { 'a'..'z' => Sym(&[c]), _ => return Err(ParseError::Unexpected(c)) }, Sym([b @ ..]) => match c { ' ' => return Ok(Sym(&b)), 'a'..'z' | '0'..'9' | '-' => Sym(&[..b, c]), _ => return Err(ParseError::Unexpected(c)) } Key([[b @ ..]]) => match c { ' ' => return Ok(Key(&[&b])), '/' => Key(&[&b, &[]]), 'a'..'z' | '0'..'9' | '-' => Key(&[&[..b, c], &[]]), _ => return Err(ParseError::Unexpected(c)) } Key([s @ .., []]) => match c { 'a'..'z' => Key(&[..s, &[c]]), _ => return Err(ParseError::Unexpected(c)) } Key([s @ .., [b @ ..]]) => match c { '/' => Key([..s, &b, &[]]), 'a'..'z' | '0'..'9' | '-' => Key(&[..s, &[..b, c]]), _ => return Err(ParseError::Unexpected(c)) } // expression must begin with key or symbol Exp([]) => match c { ' ' => Exp(&[]), ')' => return Err(ParseError::Empty), ':' => Exp(&[Sym(&[':'])]), c => Exp(&[Key(&[&[c]])]), }, // expression can't begin with number Exp([Num(num)]) => return Err(ParseError::Unexpected(c)), // symbol begins with : and lowercase a-z Exp([Sym([':'])]) => match c { 'a'..'z' => Exp(&[Sym(&[':', c])]), _ => return Err(ParseError::Unexpected(c)), }, // any other char is part of symbol until space or ) Exp([Sym([':', b @ ..])]) => match c { ')' => { tokens = &[..tokens, Exp(&[Sym(&[":", ..b])])]; Nil }, ' ' => Exp(&[Sym(&[':', ..b]), Nil]), c => Exp(&[Sym(&[':', ..b, c])]), }, // key begins with lowercase a-z Exp([Key([])]) => match c { 'a'..'z' => Exp([Key([[c]])]), _ => return Err(ParseError::Unexpected(c)), }, // any other char is part of key until slash space or ) Exp([Key([[b @ ..]])]) => match c { '/' => Exp(&[Key(&[[..b], []])]), ' ' => Exp(&[Key(&[[..b]]), Nil]), ')' => { tokens = &[..tokens, Exp(&[Sym(&[":", ..b])])]; Nil }, c => Exp(&[Key(&[[..b, c]])]) } // slash adds new section to key Exp([Key([b @ .., []])]) => match c { '/' => Exp(&[Key(&[[..b], []])]), ' ' => Exp(&[Key(&[[..b]]), Nil]), ')' => { tokens = &[..tokens, Exp(&[Sym(&[":", ..b])])]; Nil }, c => Exp(&[Key(&[[..b, c]])]) } } } Ok(state) } */ /// EDN parsing helper. #[macro_export] macro_rules! edn { ($edn:ident { $($pat:pat => $expr:expr),* $(,)? }) => { match $edn { $($pat => $expr),* } }; ($edn:ident in $args:ident { $($pat:pat => $expr:expr),* $(,)? }) => { for $edn in $args { edn!($edn { $($pat => $expr),* }) } }; } pub trait FromEdn: Sized { const ID: &'static str; fn from_edn (context: C, expr: &[Edn<'_>]) -> std::result::Result>; } /// Implements the [FromEdn] trait. #[macro_export] macro_rules! from_edn { ($id:expr => |$context:tt:$Context:ty, $args:ident| -> $T:ty $body:block) => { impl FromEdn<$Context> for $T { const ID: &'static str = $id; fn from_edn <'e> ($context: $Context, $args: &[Edn<'e>]) -> Usually { $body } } } }