mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16: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;
|
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> {
|
||||||
|
|
@ -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::*;
|
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) =>
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
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(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::*;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue