halp, i cant write a recursive iterator :3

This commit is contained in:
🪞👃🪞 2025-01-05 03:29:27 +01:00
parent f3fd88a199
commit 140fd22223
10 changed files with 107 additions and 99 deletions

1
edn/examples/edn01.edn Normal file
View file

@ -0,0 +1 @@
:test

View file

@ -2,7 +2,6 @@ use std::sync::{Arc, RwLock};
use std::collections::BTreeMap; use std::collections::BTreeMap;
pub use clojure_reader::edn::Edn; pub use clojure_reader::edn::Edn;
//#[derive(Debug, Copy, Clone, Default, PartialEq)] //#[derive(Debug, Copy, Clone, Default, PartialEq)]
//pub struct Items<'a>(&'a [Item<'a>]); //pub struct Items<'a>(&'a [Item<'a>]);
//impl<'a> Items<'a> { //impl<'a> Items<'a> {

View file

@ -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),)*
_ => {}
}
}
}
}
}

20
edn/src/edn_error.rs Normal file
View file

@ -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 {}

View file

@ -1,37 +1,5 @@
use crate::*; 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<T> { pub enum EdnItem<T> {
Nil, Nil,
Num(usize), Num(usize),
@ -44,7 +12,6 @@ impl<T> Default for EdnItem<T> {
Self::Nil Self::Nil
} }
} }
impl<T: AsRef<str> + PartialEq + Default + Clone + std::fmt::Debug> EdnItem<T> { impl<T: AsRef<str> + PartialEq + Default + Clone + std::fmt::Debug> EdnItem<T> {
pub fn to_ref (&self) -> EdnItem<&str> { pub fn to_ref (&self) -> EdnItem<&str> {
match self { match self {
@ -58,8 +25,52 @@ impl<T: AsRef<str> + PartialEq + Default + Clone + std::fmt::Debug> EdnItem<T> {
_ => todo!() _ => todo!()
} }
} }
pub fn symbols <'a> (&'a self) -> SymIterator<'a, T> {
SymIterator::new(&self)
}
}
enum SymIterator<'a, T> {
Nil,
Sym(&'a T),
Exp(&'a [EdnItem<T>])
}
impl<'a, T: AsRef<str>> SymIterator<'a, T> {
fn new (item: &'a EdnItem<T>) -> Self {
use EdnItem::*;
match item {
Sym(t) => Self::Sym(t),
Exp(i) => Self::Exp(i.as_slice()),
_ => Self::Nil,
}
}
}
impl<'a, T: AsRef<str>> Iterator for SymIterator<'a, T> {
type Item = &'a str;
fn next (&mut self) -> Option<Self::Item> {
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<String> { impl EdnItem<String> {
fn from (other: EdnItem<impl AsRef<str>>) -> EdnItem<String> { fn from (other: EdnItem<impl AsRef<str>>) -> EdnItem<String> {
use EdnItem::*; use EdnItem::*;
@ -70,7 +81,6 @@ impl EdnItem<String> {
} }
} }
} }
impl<'a> TryFrom<Token<'a>> for EdnItem<String> { impl<'a> TryFrom<Token<'a>> for EdnItem<String> {
type Error = ParseError; type Error = ParseError;
fn try_from (token: Token<'a>) -> Result<Self, Self::Error> { fn try_from (token: Token<'a>) -> Result<Self, Self::Error> {
@ -78,7 +88,7 @@ impl<'a> TryFrom<Token<'a>> for EdnItem<String> {
Ok(match token { Ok(match token {
Nil => Self::Nil, Nil => Self::Nil,
Num(chars, index, length) => Num(chars, index, length) =>
Self::Num(number(&chars[index..index+length])), Self::Num(Token::number(&chars[index..index+length])),
Sym(chars, index, length) => Sym(chars, index, length) =>
Self::Sym(String::from(&chars[index..index+length])), Self::Sym(String::from(&chars[index..index+length])),
Key(chars, index, length) => Key(chars, index, length) =>
@ -97,7 +107,7 @@ impl<'a> TryFrom<Token<'a>> for EdnItem<&'a str> {
Ok(match token { Ok(match token {
Nil => EdnItem::Nil, Nil => EdnItem::Nil,
Num(chars, index, length) => Num(chars, index, length) =>
Self::Num(number(&chars[index..index+length])), Self::Num(Token::number(&chars[index..index+length])),
Sym(chars, index, length) => Sym(chars, index, length) =>
Self::Sym(&chars[index..index+length]), Self::Sym(&chars[index..index+length]),
Key(chars, 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 { Ok(match token {
Nil => EdnItem::Nil, Nil => EdnItem::Nil,
Num(chars, index, length) => Num(chars, index, length) =>
Self::Num(number(&chars[index..index+length])), Self::Num(Token::number(&chars[index..index+length])),
Sym(chars, index, length) => Sym(chars, index, length) =>
Self::Sym(T::from(&chars[index..index+length])), Self::Sym(T::from(&chars[index..index+length])),
Key(chars, index, length) => Key(chars, index, length) =>

View file

@ -3,20 +3,6 @@ use std::marker::PhantomData;
use ::tek_layout::{*, tek_engine::{Usually, Content, Render, Engine, Thunk}}; use ::tek_layout::{*, tek_engine::{Usually, Content, Render, Engine, Thunk}};
use EdnItem::*; 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<String>,
//Box<dyn Fn(&'a T)->Box<dyn Render<E> + 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<Self> {
let (item, _): (EdnItem<String>, _) = EdnItem::read_one(&source)?;
Ok(Self(Default::default(), item))
}
}
pub type EdnRender<'a, Engine> = pub type EdnRender<'a, Engine> =
dyn Render<Engine> + Send + Sync + 'a; dyn Render<Engine> + Send + Sync + 'a;

View file

@ -55,4 +55,15 @@ impl<'a> Token<'a> {
} }
Ok(("", state)) 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!() }
}
} }

23
edn/src/edn_view.rs Normal file
View file

@ -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<String>
//render: Box<dyn Fn(&'a T)->Box<dyn Render<E> + 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<Self> {
let layout = EdnItem::read_one(&source)?.0;
for symbol in layout.symbols() {
context.import(symbol)
}
Ok(Self { _engine: Default::default(), context, layout, })
}
}

View file

@ -1,10 +1,13 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_fn_trait_return)] #![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_item; pub use self::edn_item::*;
mod edn_layout; pub use self::edn_layout::*; mod edn_layout; pub use self::edn_layout::*;
mod edn_token; pub use self::edn_token::*; mod edn_token; pub use self::edn_token::*;
mod edn_view; pub use self::edn_view::*;
#[cfg(test)] #[test] fn test_edn () -> Result<(), ParseError> { #[cfg(test)] #[test] fn test_edn () -> Result<(), ParseError> {
use EdnItem::*; use EdnItem::*;