mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
halp, i cant write a recursive iterator :3
This commit is contained in:
parent
f3fd88a199
commit
140fd22223
10 changed files with 107 additions and 99 deletions
1
edn/examples/edn01.edn
Normal file
1
edn/examples/edn01.edn
Normal file
|
|
@ -0,0 +1 @@
|
|||
:test
|
||||
|
|
@ -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> {
|
||||
|
|
@ -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
20
edn/src/edn_error.rs
Normal 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 {}
|
||||
|
|
@ -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<T> {
|
||||
Nil,
|
||||
Num(usize),
|
||||
|
|
@ -44,7 +12,6 @@ impl<T> Default for EdnItem<T> {
|
|||
Self::Nil
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<str> + PartialEq + Default + Clone + std::fmt::Debug> EdnItem<T> {
|
||||
pub fn to_ref (&self) -> EdnItem<&str> {
|
||||
match self {
|
||||
|
|
@ -58,8 +25,52 @@ impl<T: AsRef<str> + PartialEq + Default + Clone + std::fmt::Debug> EdnItem<T> {
|
|||
_ => 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> {
|
||||
fn from (other: EdnItem<impl AsRef<str>>) -> EdnItem<String> {
|
||||
use EdnItem::*;
|
||||
|
|
@ -70,7 +81,6 @@ impl EdnItem<String> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<Token<'a>> for EdnItem<String> {
|
||||
type Error = ParseError;
|
||||
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 {
|
||||
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<Token<'a>> 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) =>
|
||||
|
|
|
|||
|
|
@ -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<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> =
|
||||
dyn Render<Engine> + Send + Sync + 'a;
|
||||
|
||||
|
|
|
|||
|
|
@ -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!() }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
23
edn/src/edn_view.rs
Normal file
23
edn/src/edn_view.rs
Normal 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, })
|
||||
}
|
||||
}
|
||||
|
|
@ -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::*;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue