mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
wip: compiles and runs (not enabled yet)
This commit is contained in:
parent
ac3827b8f3
commit
98d2107e4e
15 changed files with 440 additions and 357 deletions
45
edn/src/edn_context.rs
Normal file
45
edn/src/edn_context.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
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),)*
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
60
edn/src/edn_item.rs
Normal file
60
edn/src/edn_item.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
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 {
|
||||
Empty,
|
||||
Unexpected(char),
|
||||
Incomplete
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq)]
|
||||
pub enum Item<T: AsRef<str>> {
|
||||
#[default] Nil,
|
||||
Num(usize),
|
||||
Sym(T),
|
||||
Key(T),
|
||||
Exp(Vec<Item<T>>),
|
||||
}
|
||||
|
||||
impl Item<String> {
|
||||
pub fn read_all <'a> (mut source: &'a str) -> Result<Vec<Self>, ParseError> {
|
||||
let mut items = vec![];
|
||||
loop {
|
||||
if source.len() == 0 {
|
||||
break
|
||||
}
|
||||
let (remaining, token) = Token::chomp(source)?;
|
||||
match Item::read(token)? { Item::Nil => {}, item => items.push(item) };
|
||||
source = remaining
|
||||
}
|
||||
Ok(items)
|
||||
}
|
||||
pub fn read <'a> (token: Token<'a>) -> Result<Self, ParseError> {
|
||||
use Token::*;
|
||||
Ok(match token {
|
||||
Nil => Item::Nil,
|
||||
Num(chars, index, length) =>
|
||||
Self::Num(number(&chars[index..index+length])),
|
||||
Sym(chars, index, length) =>
|
||||
Self::Sym(chars[index..index+length].to_string()),
|
||||
Key(chars, index, length) =>
|
||||
Self::Key(chars[index..index+length].to_string()),
|
||||
Exp(chars, index, length, 0) =>
|
||||
Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?),
|
||||
_ => panic!("unclosed delimiter")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -18,10 +18,10 @@ impl<'a, E, T: AsRef<str>> From<&'a [Item<T>]> for EdnContent<'a, E, T> {
|
|||
//pub struct EdnContent<'a, T>(T, &'a [Item]);
|
||||
|
||||
pub trait EdnLayout<E: Engine + 'static> {
|
||||
fn get_bool (&self, item: &Item<&str>) -> bool { todo!() }
|
||||
fn get_unit (&self, item: &Item<&str>) -> E::Unit { todo!() }
|
||||
fn get_usize (&self, key: &str) -> usize { todo!() }
|
||||
fn get_content (&self, item: &Item<&str>) -> &dyn Render<E> { todo!() }
|
||||
fn get_bool (&self, item: &Item<&str>) -> bool { false }
|
||||
fn get_unit (&self, item: &Item<&str>) -> E::Unit { 0.into() }
|
||||
fn get_usize (&self, key: &str) -> usize { 0 }
|
||||
fn get_content (&self, item: &Item<&str>) -> Box<dyn Render<E> + '_> { Box::new(()) }
|
||||
fn parse <'a: 'static> (&'a self, items: &[Item<&str>]) -> Box<dyn Render<E> + 'a> {
|
||||
match items {
|
||||
[Key("when"), c, a, ..] =>
|
||||
|
|
@ -71,50 +71,6 @@ pub trait EdnLayout<E: Engine + 'static> {
|
|||
}
|
||||
}
|
||||
|
||||
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),)*
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//edn_ns! { EdnLayout |context, item| {
|
||||
|
||||
//[Key("when"), Sym(condition), Sym(template)] => When(
|
||||
|
|
|
|||
|
|
@ -2,122 +2,6 @@ use std::sync::{Arc, RwLock};
|
|||
use std::collections::BTreeMap;
|
||||
pub use clojure_reader::edn::Edn;
|
||||
|
||||
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 {
|
||||
Empty,
|
||||
Unexpected(char),
|
||||
Incomplete
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq)]
|
||||
pub enum Item<T: AsRef<str>> {
|
||||
#[default] Nil,
|
||||
Num(usize),
|
||||
Sym(T),
|
||||
Key(T),
|
||||
Exp(Vec<Item<T>>),
|
||||
}
|
||||
|
||||
impl Item<String> {
|
||||
pub fn read_all <'a> (mut source: &'a str) -> Result<Vec<Self>, ParseError> {
|
||||
let mut items = vec![];
|
||||
loop {
|
||||
if source.len() == 0 {
|
||||
break
|
||||
}
|
||||
let (remaining, token) = Token::chomp(source)?;
|
||||
match Item::read(token)? { Item::Nil => {}, item => items.push(item) };
|
||||
source = remaining
|
||||
}
|
||||
Ok(items)
|
||||
}
|
||||
pub fn read <'a> (token: Token<'a>) -> Result<Self, ParseError> {
|
||||
use Token::*;
|
||||
Ok(match token {
|
||||
Nil => Item::Nil,
|
||||
Num(chars, index, length) =>
|
||||
Self::Num(number(&chars[index..index+length])),
|
||||
Sym(chars, index, length) =>
|
||||
Self::Sym(chars[index..index+length].to_string()),
|
||||
Key(chars, index, length) =>
|
||||
Self::Key(chars[index..index+length].to_string()),
|
||||
Exp(chars, index, length, 0) =>
|
||||
Self::Exp(Self::read_all(&chars[index+1..(index+length).saturating_sub(1)])?),
|
||||
_ => panic!("unclosed delimiter")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, PartialEq)]
|
||||
pub enum Token<'a> {
|
||||
#[default] Nil,
|
||||
Num(&'a str, usize, usize),
|
||||
Sym(&'a str, usize, usize),
|
||||
Key(&'a str, usize, usize),
|
||||
Exp(&'a str, usize, usize, usize),
|
||||
}
|
||||
|
||||
impl<'a> Token<'a> {
|
||||
fn chomp (source: &'a str) -> Result<(&'a str, Self), ParseError> {
|
||||
use Token::*;
|
||||
let mut state = Self::default();
|
||||
for (index, c) in source.char_indices() {
|
||||
state = match state {
|
||||
// must begin expression
|
||||
Nil => match c {
|
||||
' '|'\n'|'\r'|'\t' => Nil,
|
||||
'(' => Exp(source, index, 1, 1),
|
||||
':' => Sym(source, index, 1),
|
||||
'0'..='9' => Num(source, index, 1),
|
||||
'a'..='z' => Key(source, index, 1),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Num(_, _, 0) => unreachable!(),
|
||||
Sym(_, _, 0) => unreachable!(),
|
||||
Key(_, _, 0) => unreachable!(),
|
||||
Num(source, index, length) => match c {
|
||||
'0'..='9' => Num(source, index, length + 1),
|
||||
' '|'\n'|'\r'|'\t' => return Ok((&source[index+length..], Num(source, index, length))),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Sym(source, index, length) => match c {
|
||||
'a'..='z'|'0'..='9'|'-' => Sym(source, index, length + 1),
|
||||
' '|'\n'|'\r'|'\t' => return Ok((&source[index+length..], Sym(source, index, length))),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Key(source, index, length) => match c {
|
||||
'a'..='z'|'0'..='9'|'-'|'/' => Key(source, index, length + 1),
|
||||
' '|'\n'|'\r'|'\t' => return Ok((&source[index+length..], Key(source, index, length))),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Exp(source, index, length, 0) => match c {
|
||||
' '|'\n'|'\r'|'\t' => return Ok((&source[index+length..], Exp(source, index, length, 0))),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Exp(source, index, length, depth) => match c {
|
||||
')' => Exp(source, index, length + 1, depth - 1),
|
||||
'(' => Exp(source, index, length + 1, depth + 1),
|
||||
_ => Exp(source, index, length + 1, depth)
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(("", state))
|
||||
}
|
||||
}
|
||||
|
||||
//#[derive(Debug, Copy, Clone, Default, PartialEq)]
|
||||
//pub struct Items<'a>(&'a [Item<'a>]);
|
||||
|
|
|
|||
58
edn/src/edn_token.rs
Normal file
58
edn/src/edn_token.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
use crate::*;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Default, PartialEq)]
|
||||
pub enum Token<'a> {
|
||||
#[default] Nil,
|
||||
Num(&'a str, usize, usize),
|
||||
Sym(&'a str, usize, usize),
|
||||
Key(&'a str, usize, usize),
|
||||
Exp(&'a str, usize, usize, usize),
|
||||
}
|
||||
|
||||
impl<'a> Token<'a> {
|
||||
pub fn chomp (source: &'a str) -> Result<(&'a str, Self), ParseError> {
|
||||
use Token::*;
|
||||
let mut state = Self::default();
|
||||
for (index, c) in source.char_indices() {
|
||||
state = match state {
|
||||
// must begin expression
|
||||
Nil => match c {
|
||||
' '|'\n'|'\r'|'\t' => Nil,
|
||||
'(' => Exp(source, index, 1, 1),
|
||||
':' => Sym(source, index, 1),
|
||||
'0'..='9' => Num(source, index, 1),
|
||||
'a'..='z' => Key(source, index, 1),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Num(_, _, 0) => unreachable!(),
|
||||
Sym(_, _, 0) => unreachable!(),
|
||||
Key(_, _, 0) => unreachable!(),
|
||||
Num(source, index, length) => match c {
|
||||
'0'..='9' => Num(source, index, length + 1),
|
||||
' '|'\n'|'\r'|'\t' => return Ok((&source[index+length..], Num(source, index, length))),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Sym(source, index, length) => match c {
|
||||
'a'..='z'|'0'..='9'|'-' => Sym(source, index, length + 1),
|
||||
' '|'\n'|'\r'|'\t' => return Ok((&source[index+length..], Sym(source, index, length))),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Key(source, index, length) => match c {
|
||||
'a'..='z'|'0'..='9'|'-'|'/' => Key(source, index, length + 1),
|
||||
' '|'\n'|'\r'|'\t' => return Ok((&source[index+length..], Key(source, index, length))),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Exp(source, index, length, 0) => match c {
|
||||
' '|'\n'|'\r'|'\t' => return Ok((&source[index+length..], Exp(source, index, length, 0))),
|
||||
_ => return Err(ParseError::Unexpected(c))
|
||||
},
|
||||
Exp(source, index, length, depth) => match c {
|
||||
')' => Exp(source, index, length + 1, depth - 1),
|
||||
'(' => Exp(source, index, length + 1, depth + 1),
|
||||
_ => Exp(source, index, length + 1, depth)
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(("", state))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(impl_trait_in_fn_trait_return)]
|
||||
|
||||
mod edn_lib; pub use self::edn_lib::*;
|
||||
mod edn_layout; pub use self::edn_layout::*;
|
||||
mod edn_context; pub use self::edn_context::*;
|
||||
mod edn_item; pub use self::edn_item::*;
|
||||
mod edn_layout; pub use self::edn_layout::*;
|
||||
mod edn_token; pub use self::edn_token::*;
|
||||
|
||||
#[cfg(test)] #[test] fn test_edn () -> Result<(), ParseError> {
|
||||
use Item::*;
|
||||
|
|
@ -28,7 +30,7 @@ mod edn_layout; pub use self::edn_layout::*;
|
|||
#[cfg(test)] #[test] fn test_edn_layout () -> Result<(), ParseError> {
|
||||
let source = include_str!("example.edn");
|
||||
let layout = Item::read_all(source)?;
|
||||
panic!("{layout:?}");
|
||||
let content = EdnLayout::from(&layout);
|
||||
//panic!("{layout:?}");
|
||||
//let content = <dyn EdnLayout<::tek_engine::tui::Tui>>::from(&layout);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue