diff options
| -rw-r--r-- | Cargo.lock | 5 | ||||
| -rw-r--r-- | Cargo.toml | 4 | ||||
| -rw-r--r-- | crimtag/src/context.rs | 71 | ||||
| -rw-r--r-- | derive/Cargo.toml | 4 | ||||
| -rw-r--r-- | derive/src/lib.rs | 30 | ||||
| -rw-r--r-- | derive/tests/basic.rs | 9 | ||||
| -rw-r--r-- | lookahead/Cargo.toml | 6 | ||||
| -rw-r--r-- | lookahead/src/lib.rs | 84 |
8 files changed, 179 insertions, 34 deletions
| @@ -11,4 +11,9 @@ name = "derive" | |||
| 11 | version = "0.1.0" | 11 | version = "0.1.0" |
| 12 | dependencies = [ | 12 | dependencies = [ |
| 13 | "crimtag", | 13 | "crimtag", |
| 14 | "lookahead", | ||
| 14 | ] | 15 | ] |
| 16 | |||
| 17 | [[package]] | ||
| 18 | name = "lookahead" | ||
| 19 | version = "0.1.0" | ||
| @@ -1,6 +1,6 @@ | |||
| 1 | [workspace] | 1 | [workspace] |
| 2 | members = ["derive","crimtag"] | 2 | members = ["derive","crimtag", "lookahead"] |
| 3 | default-members = ["derive","crimtag"] | 3 | default-members = ["lookahead", "derive","crimtag"] |
| 4 | resolver = "3" | 4 | resolver = "3" |
| 5 | 5 | ||
| 6 | [workspace.dependencies] | 6 | [workspace.dependencies] |
diff --git a/crimtag/src/context.rs b/crimtag/src/context.rs index 6f8e04f..15448ee 100644 --- a/crimtag/src/context.rs +++ b/crimtag/src/context.rs | |||
| @@ -107,24 +107,63 @@ pub enum MappedValue<'a> { | |||
| 107 | impl<'a> fmt::Debug for MappedValue<'a> { | 107 | impl<'a> fmt::Debug for MappedValue<'a> { |
| 108 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 108 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 109 | match self { | 109 | match self { |
| 110 | MappedValue::<'a>::Struct(_) => write!(f, "MappedValue"), | 110 | MappedValue::<'a>::Struct(_) => write!(f, "MappedValue"), |
| 111 | MappedValue::<'a>::List(_) => write!(f, "MappedList"), | 111 | MappedValue::<'a>::List(_) => write!(f, "MappedList"), |
| 112 | MappedValue::<'a>::Str(v) => write!(f, "{:?}", v), | 112 | MappedValue::<'a>::Str(v) => write!(f, "{:?}", v), |
| 113 | MappedValue::<'a>::String(v) => write!(f, "{:?}", v), | 113 | MappedValue::<'a>::String(v) => write!(f, "{:?}", v), |
| 114 | MappedValue::<'a>::Int8(v) => write!(f, "{:?}", v), | 114 | MappedValue::<'a>::Int8(v) => write!(f, "{:?}", v), |
| 115 | MappedValue::<'a>::Int16(v) => write!(f, "{:?}", v), | 115 | MappedValue::<'a>::Int16(v) => write!(f, "{:?}", v), |
| 116 | MappedValue::<'a>::Int32(v) => write!(f, "{:?}", v), | 116 | MappedValue::<'a>::Int32(v) => write!(f, "{:?}", v), |
| 117 | MappedValue::<'a>::Int64(v) => write!(f, "{:?}", v), | 117 | MappedValue::<'a>::Int64(v) => write!(f, "{:?}", v), |
| 118 | MappedValue::<'a>::UInt8(v) => write!(f, "{:?}", v), | 118 | MappedValue::<'a>::UInt8(v) => write!(f, "{:?}", v), |
| 119 | MappedValue::<'a>::UInt16(v) => write!(f, "{:?}", v), | 119 | MappedValue::<'a>::UInt16(v) => write!(f, "{:?}", v), |
| 120 | MappedValue::<'a>::UInt32(v) => write!(f, "{:?}", v), | 120 | MappedValue::<'a>::UInt32(v) => write!(f, "{:?}", v), |
| 121 | MappedValue::<'a>::UInt64(v) => write!(f, "{:?}", v), | 121 | MappedValue::<'a>::UInt64(v) => write!(f, "{:?}", v), |
| 122 | MappedValue::<'a>::Float32(v) => write!(f, "{:?}", v), | 122 | MappedValue::<'a>::Float32(v) => write!(f, "{:?}", v), |
| 123 | MappedValue::<'a>::Float64(v) => write!(f, "{:?}", v), | 123 | MappedValue::<'a>::Float64(v) => write!(f, "{:?}", v), |
| 124 | MappedValue::<'a>::Bool(v) => write!(f, "{:?}", v), | 124 | MappedValue::<'a>::Bool(v) => write!(f, "{:?}", v), |
| 125 | } | 125 | } |
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | macro_rules! basic_mapped_value_from { | ||
| 130 | ( $x:ident, $y:ident ) => { | ||
| 131 | impl<'a> From<&$x> for MappedValue<'a> { | ||
| 132 | fn from(val: &$x) -> MappedValue<'a> { | ||
| 133 | MappedValue::$y(*val) | ||
| 134 | } | ||
| 135 | } | ||
| 136 | }; | ||
| 137 | } | ||
| 138 | |||
| 139 | basic_mapped_value_from!(i8, Int8); | ||
| 140 | basic_mapped_value_from!(i16, Int16); | ||
| 141 | basic_mapped_value_from!(i32, Int32); | ||
| 142 | basic_mapped_value_from!(i64, Int64); | ||
| 143 | basic_mapped_value_from!(u8, UInt8); | ||
| 144 | basic_mapped_value_from!(u16, UInt16); | ||
| 145 | basic_mapped_value_from!(u32, UInt32); | ||
| 146 | basic_mapped_value_from!(u64, UInt64); | ||
| 147 | basic_mapped_value_from!(f32, Float32); | ||
| 148 | basic_mapped_value_from!(f64, Float64); | ||
| 149 | basic_mapped_value_from!(bool, Bool); | ||
| 150 | |||
| 151 | impl<'a> From<&'a String> for MappedValue<'a> { | ||
| 152 | fn from(val: &'a String ) -> MappedValue<'a> { | ||
| 153 | MappedValue::String(val) | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | impl<'a, T: MappedStructure<'a>> From<&'a Vec<T>> for MappedValue<'a> { | ||
| 158 | fn from(val: &'a Vec<T> ) -> MappedValue<'a> { | ||
| 159 | MappedValue::List(val) | ||
| 160 | } | ||
| 161 | } | ||
| 162 | |||
| 163 | impl<'a,T: MappedStructure<'a>> From<&'a T> for MappedValue<'a> { | ||
| 164 | fn from(val: &'a T ) -> MappedValue<'a> { | ||
| 165 | MappedValue::Struct(val) | ||
| 126 | } | 166 | } |
| 127 | |||
| 128 | } | 167 | } |
| 129 | 168 | ||
| 130 | pub struct StatefulContext<'a> { | 169 | pub struct StatefulContext<'a> { |
diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 65f3a75..bb5ddf3 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml | |||
| @@ -6,5 +6,9 @@ edition = "2024" | |||
| 6 | [lib] | 6 | [lib] |
| 7 | proc-macro = true | 7 | proc-macro = true |
| 8 | 8 | ||
| 9 | [dependencies] | ||
| 10 | lookahead = {path="../lookahead"} | ||
| 11 | |||
| 9 | [dev-dependencies] | 12 | [dev-dependencies] |
| 10 | crimtag = { path = "../crimtag"} | 13 | crimtag = { path = "../crimtag"} |
| 14 | |||
diff --git a/derive/src/lib.rs b/derive/src/lib.rs index f9c9180..bb299d0 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs | |||
| @@ -1,9 +1,11 @@ | |||
| 1 | extern crate proc_macro; | 1 | extern crate proc_macro; |
| 2 | use proc_macro::{TokenStream,TokenTree,Ident,Delimiter}; | 2 | use proc_macro::{TokenStream,TokenTree,Ident,Delimiter}; |
| 3 | 3 | ||
| 4 | use lookahead::LookAhead; | ||
| 5 | |||
| 4 | #[proc_macro_derive(CrimtagMappable)] | 6 | #[proc_macro_derive(CrimtagMappable)] |
| 5 | pub fn derive_crimtag_mappable(s: TokenStream) -> TokenStream { | 7 | pub fn derive_crimtag_mappable(s: TokenStream) -> TokenStream { |
| 6 | let mut i = s.into_iter(); | 8 | let mut i = LookAhead::<2,_,_>::new(s.into_iter()); |
| 7 | while let Some(t) = i.next() { | 9 | while let Some(t) = i.next() { |
| 8 | if let TokenTree::Ident(ident) = t && | 10 | if let TokenTree::Ident(ident) = t && |
| 9 | ident.to_string() == "struct" { | 11 | ident.to_string() == "struct" { |
| @@ -18,7 +20,7 @@ pub fn derive_crimtag_mappable(s: TokenStream) -> TokenStream { | |||
| 18 | 20 | ||
| 19 | // TODO: Expand this to include the generic parameters and the where? at | 21 | // TODO: Expand this to include the generic parameters and the where? at |
| 20 | // least the parameters. | 22 | // least the parameters. |
| 21 | println!("struct name: {:?}", name); | 23 | //println!("struct name: {:?}", name); |
| 22 | 24 | ||
| 23 | let mut newfunc = format!( | 25 | let mut newfunc = format!( |
| 24 | r#"impl<'a> crimtag::MappedStructure<'a> for {} {{ | 26 | r#"impl<'a> crimtag::MappedStructure<'a> for {} {{ |
| @@ -34,24 +36,20 @@ r#"impl<'a> crimtag::MappedStructure<'a> for {} {{ | |||
| 34 | if let TokenTree::Group(g) = &n && | 36 | if let TokenTree::Group(g) = &n && |
| 35 | g.delimiter() == Delimiter::Brace { | 37 | g.delimiter() == Delimiter::Brace { |
| 36 | // Operate on the struct members. | 38 | // Operate on the struct members. |
| 37 | let mut gi = g.stream().into_iter(); | 39 | let mut gi = LookAhead::<2,_,_>::new(g.stream().into_iter()); |
| 38 | let mut cur = 0usize; | ||
| 39 | let mut tok = [gi.next(), gi.next()]; | ||
| 40 | loop { | 40 | loop { |
| 41 | if let Some(TokenTree::Punct(ch)) = &tok[(cur+1)%2] && | 41 | if let Some(TokenTree::Punct(ch)) = gi.peek(1) && |
| 42 | ch.as_char() == ':' && | 42 | ch.as_char() == ':' && |
| 43 | let Some(TokenTree::Ident(id)) = &tok[cur] { | 43 | let Some(TokenTree::Ident(id)) = gi.peek(0) { |
| 44 | println!("!!!!!!!!!! -> {}", id); | 44 | //println!("!!!!!!!!!! -> {}", id); |
| 45 | newfunc.push_str(&format!( | 45 | newfunc.push_str(&format!( |
| 46 | r#" "{}" => Some(self.{}.into()), | 46 | r#" "{}" => Some((&self.{}).into()), |
| 47 | "#, id, id)); | 47 | "#, id, id)); |
| 48 | } | 48 | } |
| 49 | println!(" - {:?} {:?}", tok[cur], tok[(cur+1)%2] ); | 49 | //println!(" -> {:?} ", gi.peek(0)); |
| 50 | //println!(" {:?}", gi.peek(1) ); | ||
| 50 | // Update next. | 51 | // Update next. |
| 51 | if let Some(ni) = gi.next() { | 52 | if gi.next().is_none() { |
| 52 | tok[cur].replace( ni ); | ||
| 53 | cur = (cur+1)%2; | ||
| 54 | } else { | ||
| 55 | break; | 53 | break; |
| 56 | } | 54 | } |
| 57 | } | 55 | } |
| @@ -63,13 +61,13 @@ r#" _ => None, | |||
| 63 | } | 61 | } |
| 64 | } | 62 | } |
| 65 | }"#); | 63 | }"#); |
| 66 | 64 | /* | |
| 67 | println!(); | 65 | println!(); |
| 68 | println!(); | 66 | println!(); |
| 69 | println!("{}", newfunc); | 67 | println!("{}", newfunc); |
| 70 | println!(); | 68 | println!(); |
| 71 | println!(); | 69 | println!(); |
| 72 | 70 | */ | |
| 73 | newfunc.parse().unwrap() | 71 | newfunc.parse().unwrap() |
| 74 | } | 72 | } |
| 75 | 73 | ||
diff --git a/derive/tests/basic.rs b/derive/tests/basic.rs index 18fc366..a636faa 100644 --- a/derive/tests/basic.rs +++ b/derive/tests/basic.rs | |||
| @@ -2,10 +2,19 @@ use derive::*; | |||
| 2 | use crimtag::*; | 2 | use crimtag::*; |
| 3 | 3 | ||
| 4 | #[derive(CrimtagMappable)] | 4 | #[derive(CrimtagMappable)] |
| 5 | pub struct SubTest { | ||
| 6 | name: String, | ||
| 7 | byline: String, | ||
| 8 | amount: i64, | ||
| 9 | } | ||
| 10 | |||
| 11 | #[derive(CrimtagMappable)] | ||
| 5 | pub struct Test { | 12 | pub struct Test { |
| 6 | number: i32, | 13 | number: i32, |
| 7 | something: f64, | 14 | something: f64, |
| 8 | inner_thing: String, | 15 | inner_thing: String, |
| 16 | sub: SubTest, | ||
| 17 | stuff: Vec<SubTest>, | ||
| 9 | } | 18 | } |
| 10 | 19 | ||
| 11 | 20 | ||
diff --git a/lookahead/Cargo.toml b/lookahead/Cargo.toml new file mode 100644 index 0000000..d79f913 --- /dev/null +++ b/lookahead/Cargo.toml | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | [package] | ||
| 2 | name = "lookahead" | ||
| 3 | version = "0.1.0" | ||
| 4 | edition = "2024" | ||
| 5 | |||
| 6 | [dependencies] | ||
diff --git a/lookahead/src/lib.rs b/lookahead/src/lib.rs new file mode 100644 index 0000000..08bf20e --- /dev/null +++ b/lookahead/src/lib.rs | |||
| @@ -0,0 +1,84 @@ | |||
| 1 | pub struct LookAhead<const C: usize, T, U> | ||
| 2 | where | ||
| 3 | U: Iterator<Item=T> + Sized | ||
| 4 | { | ||
| 5 | iter: U, | ||
| 6 | data: [Option<T>;C], | ||
| 7 | cur: usize, | ||
| 8 | fill: usize, | ||
| 9 | } | ||
| 10 | |||
| 11 | impl<const C: usize, T, U> LookAhead<C,T,U> | ||
| 12 | where | ||
| 13 | U: Iterator<Item=T> + Sized | ||
| 14 | { | ||
| 15 | pub fn new(iter: U) -> Self { | ||
| 16 | Self { | ||
| 17 | iter, | ||
| 18 | data: [const {None};C], | ||
| 19 | cur: 0, | ||
| 20 | fill: 0, | ||
| 21 | } | ||
| 22 | } | ||
| 23 | |||
| 24 | pub fn peek(&mut self, offset: usize) -> Option<&T> { | ||
| 25 | assert!(offset<C); | ||
| 26 | self.fill_to( offset ); | ||
| 27 | self.data[(self.cur+offset)%C].as_ref() | ||
| 28 | } | ||
| 29 | |||
| 30 | fn fill_to(&mut self, qty: usize) { | ||
| 31 | for i in self.fill..=qty { | ||
| 32 | if let Some(x) = self.iter.next() { | ||
| 33 | self.data[(self.cur+i)%C].replace( x ); | ||
| 34 | self.fill += 1; | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | impl<const C: usize, T, U> std::iter::Iterator for LookAhead<C,T,U> | ||
| 41 | where | ||
| 42 | U: Iterator<Item=T> + Sized | ||
| 43 | { | ||
| 44 | type Item=T; | ||
| 45 | |||
| 46 | fn next(&mut self) -> Option<T> { | ||
| 47 | if self.fill == 0 { | ||
| 48 | self.iter.next() | ||
| 49 | } else { | ||
| 50 | let old = self.cur; | ||
| 51 | self.cur = (self.cur+1)%C; | ||
| 52 | self.fill -= 1; | ||
| 53 | self.data[old].take() | ||
| 54 | } | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | #[cfg(test)] | ||
| 59 | mod tests { | ||
| 60 | use super::*; | ||
| 61 | |||
| 62 | #[test] | ||
| 63 | fn basic() { | ||
| 64 | let data = [1, 2, 3, 4, 5, 6, 7, 8]; | ||
| 65 | let mut i = LookAhead::<3,_,_>::new(data.iter()); | ||
| 66 | assert_eq!(i.next(), Some(&1)); | ||
| 67 | assert_eq!(i.peek(1), Some(&&3)); | ||
| 68 | assert_eq!(i.peek(0), Some(&&2)); | ||
| 69 | assert_eq!(i.next(), Some(&2)); | ||
| 70 | assert_eq!(i.peek(0), Some(&&3)); | ||
| 71 | assert_eq!(i.next(), Some(&3)); | ||
| 72 | assert_eq!(i.next(), Some(&4)); | ||
| 73 | assert_eq!(i.next(), Some(&5)); | ||
| 74 | assert_eq!(i.peek(0), Some(&&6)); | ||
| 75 | assert_eq!(i.peek(1), Some(&&7)); | ||
| 76 | assert_eq!(i.peek(2), Some(&&8)); | ||
| 77 | assert_eq!(i.next(), Some(&6)); | ||
| 78 | assert_eq!(i.peek(2), None); | ||
| 79 | assert_eq!(i.next(), Some(&7)); | ||
| 80 | assert_eq!(i.peek(2), None); | ||
| 81 | assert_eq!(i.next(), Some(&8)); | ||
| 82 | assert_eq!(i.next(), None); | ||
| 83 | } | ||
| 84 | } | ||
