diff --git a/edn/examples/edn01.edn b/edn/examples/edn01.edn new file mode 100644 index 00000000..aa803c29 --- /dev/null +++ b/edn/examples/edn01.edn @@ -0,0 +1 @@ +:test diff --git a/edn/src/example.edn b/edn/examples/edn02.edn similarity index 100% rename from edn/src/example.edn rename to edn/examples/edn02.edn diff --git a/edn/src/edn_lib.rs b/edn/src/_edn_scratch.rs similarity index 99% rename from edn/src/edn_lib.rs rename to edn/src/_edn_scratch.rs index 7233d310..c6e9d9f5 100644 --- a/edn/src/edn_lib.rs +++ b/edn/src/_edn_scratch.rs @@ -2,7 +2,6 @@ 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> { diff --git a/edn/src/edn_context.rs b/edn/src/edn_context.rs deleted file mode 100644 index c051d08d..00000000 --- a/edn/src/edn_context.rs +++ /dev/null @@ -1,45 +0,0 @@ -use crate::*; - -#[macro_export] macro_rules! edn_context { - ($Struct:ident |$l:lifetime, $state:ident| { - $($key:literal = $field:ident: $Type:ty => $expr:expr,)* - }) => { - - #[derive(Default)] - pub struct EdnView<$l> { $($field: Option<$Type>),* } - - impl<$l> EdnView<$l> { - pub fn parse <'e> (edn: &[Edn<'e>]) -> impl Fn(&$Struct) + use<'e> { - let imports = Self::imports_all(edn); - move |state| { - let mut context = EdnView::default(); - for import in imports.iter() { - context.import(state, import) - } - } - } - fn imports_all <'e> (edn: &[Edn<'e>]) -> Vec<&'e str> { - let mut imports = vec![]; - for edn in edn.iter() { - for import in Self::imports_one(edn) { - imports.push(import); - } - } - imports - } - fn imports_one <'e> (edn: &Edn<'e>) -> Vec<&'e str> { - match edn { - Edn::Symbol(import) => vec![import], - Edn::List(edn) => Self::imports_all(edn.as_slice()), - _ => vec![], - } - } - pub fn import (&mut self, $state: &$l$Struct, key: &str) { - match key { - $($key => self.$field = Some($expr),)* - _ => {} - } - } - } - } -} diff --git a/edn/src/edn_error.rs b/edn/src/edn_error.rs new file mode 100644 index 00000000..56028378 --- /dev/null +++ b/edn/src/edn_error.rs @@ -0,0 +1,20 @@ +use crate::*; + +#[derive(Debug)] +pub enum ParseError { + Unknown(u8), + Empty, + Incomplete, + Unexpected(char), +} +impl std::fmt::Display for ParseError { + fn fmt (&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Self::Empty => write!(f, "empty"), + Self::Incomplete => write!(f, "incomplete"), + Self::Unexpected(c) => write!(f, "unexpected '{c}'"), + Self::Unknown(i) => write!(f, "unknown #{i}"), + } + } +} +impl std::error::Error for ParseError {} diff --git a/edn/src/edn_item.rs b/edn/src/edn_item.rs index ffa8fabf..f7091d8a 100644 --- a/edn/src/edn_item.rs +++ b/edn/src/edn_item.rs @@ -1,37 +1,5 @@ use crate::*; -fn number (digits: &str) -> usize { - let mut value = 0; - for c in digits.chars() { - value = 10 * value + digit(c); - } - value -} - -const fn digit (c: char) -> usize { - match c { '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, - '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, _ => unreachable!() } -} - -#[derive(Debug)] -pub enum ParseError { - Unknown(u8), - Empty, - Incomplete, - Unexpected(char), -} -impl std::fmt::Display for ParseError { - fn fmt (&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - Self::Empty => write!(f, "empty"), - Self::Incomplete => write!(f, "incomplete"), - Self::Unexpected(c) => write!(f, "unexpected '{c}'"), - Self::Unknown(i) => write!(f, "unknown #{i}"), - } - } -} -impl std::error::Error for ParseError {} - pub enum EdnItem { Nil, Num(usize), @@ -44,7 +12,6 @@ impl Default for EdnItem { Self::Nil } } - impl + PartialEq + Default + Clone + std::fmt::Debug> EdnItem { pub fn to_ref (&self) -> EdnItem<&str> { match self { @@ -58,8 +25,52 @@ impl + PartialEq + Default + Clone + std::fmt::Debug> EdnItem { _ => todo!() } } + pub fn symbols <'a> (&'a self) -> SymIterator<'a, T> { + SymIterator::new(&self) + } +} +enum SymIterator<'a, T> { + Nil, + Sym(&'a T), + Exp(&'a [EdnItem]) +} +impl<'a, T: AsRef> SymIterator<'a, T> { + fn new (item: &'a EdnItem) -> Self { + use EdnItem::*; + match item { + Sym(t) => Self::Sym(t), + Exp(i) => Self::Exp(i.as_slice()), + _ => Self::Nil, + } + } +} +impl<'a, T: AsRef> Iterator for SymIterator<'a, T> { + type Item = &'a str; + fn next (&mut self) -> Option { + use SymIterator::*; + match self { + Sym(t) => { + *self = Nil; + Some(t.as_ref()) + }, + Exp([a, b @ ..]) => match a { + EdnItem::Sym(t) => { + *self = Exp(b); + Some(t.as_ref()) + } + EdnItem::Exp(_) => todo!(), + _ => { + *self = Nil; + None + } + }, + _ => { + *self = Nil; + None + } + } + } } - impl EdnItem { fn from (other: EdnItem>) -> EdnItem { use EdnItem::*; @@ -70,7 +81,6 @@ impl EdnItem { } } } - impl<'a> TryFrom> for EdnItem { type Error = ParseError; fn try_from (token: Token<'a>) -> Result { @@ -78,7 +88,7 @@ impl<'a> TryFrom> for EdnItem { Ok(match token { Nil => Self::Nil, Num(chars, index, length) => - Self::Num(number(&chars[index..index+length])), + Self::Num(Token::number(&chars[index..index+length])), Sym(chars, index, length) => Self::Sym(String::from(&chars[index..index+length])), Key(chars, index, length) => @@ -97,7 +107,7 @@ impl<'a> TryFrom> for EdnItem<&'a str> { Ok(match token { Nil => EdnItem::Nil, Num(chars, index, length) => - Self::Num(number(&chars[index..index+length])), + Self::Num(Token::number(&chars[index..index+length])), Sym(chars, index, length) => Self::Sym(&chars[index..index+length]), Key(chars, index, length) => @@ -136,7 +146,7 @@ impl<'a, T: std::fmt::Debug + Clone + Default + PartialEq + From<&'a str>> EdnIt Ok(match token { Nil => EdnItem::Nil, Num(chars, index, length) => - Self::Num(number(&chars[index..index+length])), + Self::Num(Token::number(&chars[index..index+length])), Sym(chars, index, length) => Self::Sym(T::from(&chars[index..index+length])), Key(chars, index, length) => diff --git a/edn/src/edn_layout.rs b/edn/src/edn_layout.rs index 83217dfe..e5156ba1 100644 --- a/edn/src/edn_layout.rs +++ b/edn/src/edn_layout.rs @@ -3,20 +3,6 @@ use std::marker::PhantomData; use ::tek_layout::{*, tek_engine::{Usually, Content, Render, Engine, Thunk}}; use EdnItem::*; -/// Compiles view from EDN form to Thunk -pub struct EdnView<'a, E: Engine + 'a, T: EdnLayout<'a, E> + 'a>( - PhantomData<&'a (E, T)>, - EdnItem, - //BoxBox + Send + Sync + 'a> + Send + Sync + 'a> -); - -impl<'a, E: Engine + 'a, T: EdnLayout<'a, E> + 'a> EdnView<'a, E, T> { - pub fn new (source: &'a str) -> Usually { - let (item, _): (EdnItem, _) = EdnItem::read_one(&source)?; - Ok(Self(Default::default(), item)) - } -} - pub type EdnRender<'a, Engine> = dyn Render + Send + Sync + 'a; diff --git a/edn/src/edn_token.rs b/edn/src/edn_token.rs index 791e9657..4428c0b3 100644 --- a/edn/src/edn_token.rs +++ b/edn/src/edn_token.rs @@ -55,4 +55,15 @@ impl<'a> Token<'a> { } Ok(("", state)) } + + pub fn number (digits: &str) -> usize { + let mut value = 0; + for c in digits.chars() { value = 10 * value + Self::digit(c); } + value + } + + pub const fn digit (c: char) -> usize { + match c { '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, + '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, _ => unreachable!() } + } } diff --git a/edn/src/edn_view.rs b/edn/src/edn_view.rs new file mode 100644 index 00000000..a005d0ca --- /dev/null +++ b/edn/src/edn_view.rs @@ -0,0 +1,23 @@ +use crate::*; +use std::marker::PhantomData; +use EdnItem::*; + +use EdnItem::*; + +/// Renders from EDN source and context. +pub struct EdnView<'a, E: Engine + 'a, T: EdnLayout<'a, E> + 'a> { + _engine: PhantomData<&'a E>, + context: T, + layout: EdnItem + //render: BoxBox + Send + Sync + 'a> + Send + Sync + 'a> +} + +impl<'a, E: Engine + 'a, T: EdnLayout<'a, E> + 'a> EdnView<'a, E, T> { + pub fn new (context: T, source: &'a str) -> Usually { + let layout = EdnItem::read_one(&source)?.0; + for symbol in layout.symbols() { + context.import(symbol) + } + Ok(Self { _engine: Default::default(), context, layout, }) + } +} diff --git a/edn/src/lib.rs b/edn/src/lib.rs index 8540d308..bcd2033f 100644 --- a/edn/src/lib.rs +++ b/edn/src/lib.rs @@ -1,10 +1,13 @@ #![feature(type_alias_impl_trait)] #![feature(impl_trait_in_fn_trait_return)] -mod edn_context; pub use self::edn_context::*; +pub(crate) use ::tek_layout::{*, tek_engine::{Usually, Content, Render, Engine, Thunk}}; + +mod edn_error; pub use self::edn_error::*; mod edn_item; pub use self::edn_item::*; mod edn_layout; pub use self::edn_layout::*; mod edn_token; pub use self::edn_token::*; +mod edn_view; pub use self::edn_view::*; #[cfg(test)] #[test] fn test_edn () -> Result<(), ParseError> { use EdnItem::*;