Skip to content

Commit cdc4cb6

Browse files
2.2: 完成let 变量绑定的实现
1 parent 269600c commit cdc4cb6

File tree

4 files changed

+105
-28
lines changed

4 files changed

+105
-28
lines changed

src/eager_evaluation.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,26 @@ pub use linked_list::LinkedListComprehension;
1616
pub use vec_deque::VecDequeComprehension;
1717
pub use vector::VecComprehension;
1818

19-
use crate::iter_clause::{BareIfClause, ForInClause, IterClause};
19+
use crate::iter_clause::{BareIfClause, ForInClause, IterClause, LetClause};
2020

2121
use proc_macro2::TokenStream;
2222
use quote::quote;
2323
use syn::Expr;
2424

25-
pub(crate) fn handle_nested_loops<'a>(
26-
iter_clauses: &'a [IterClause],
25+
pub(crate) fn handle_nested_loops(
26+
iter_clauses: &[IterClause],
2727
mut nested_code: TokenStream,
2828
) -> TokenStream {
29-
let mut need_to_shadow: Vec<&'a Expr> = vec![];
29+
let mut need_to_shadow: Vec<&Expr> = vec![];
3030

3131
// 遍历iter_clauses(因为越向后层次越深, 所以直接pop就行了)
32-
let mut iter_clauses: Vec<&'a IterClause> = iter_clauses.iter().collect();
32+
let mut iter_clauses: Vec<&IterClause> = iter_clauses.iter().collect();
3333

3434
while let Some(iter_clause) = iter_clauses.pop() {
3535
let IterClause {
3636
for_in_clause: ForInClause { pat, iterable },
3737
if_clause,
38+
let_clauses,
3839
} = iter_clause;
3940

4041
let iterable_code = match iterable {
@@ -57,6 +58,14 @@ pub(crate) fn handle_nested_loops<'a>(
5758
_ => panic!("type is not supported: \n{:#?}", iterable),
5859
};
5960

61+
let mut let_clauses: Vec<&LetClause> = let_clauses.iter().collect();
62+
while let Some(LetClause { let_expr }) = let_clauses.pop() {
63+
nested_code = quote! {
64+
#let_expr;
65+
#nested_code
66+
};
67+
}
68+
6069
// 根据是否有if条件生成循环代码
6170
nested_code = match if_clause {
6271
Some(BareIfClause { conditions }) => {

src/iter_clause.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,25 @@ use syn::parse::ParseStream;
77
pub struct IterClause {
88
pub for_in_clause: ForInClause,
99
pub if_clause: Option<BareIfClause>,
10+
pub let_clauses: Vec<LetClause>,
1011
}
1112

1213
impl syn::parse::Parse for IterClause {
1314
fn parse(input: ParseStream) -> syn::Result<Self> {
1415
let mut iter_clause = Self {
1516
for_in_clause: input.parse::<ForInClause>()?,
1617
if_clause: None,
18+
let_clauses: vec![],
1719
};
1820

1921
if input.peek(syn::Token![if]) {
2022
iter_clause.if_clause = Some(input.parse::<BareIfClause>()?);
2123
}
2224

25+
while input.peek(syn::Token![let]) {
26+
iter_clause.let_clauses.push(input.parse::<LetClause>()?);
27+
}
28+
2329
Ok(iter_clause)
2430
}
2531
}
@@ -59,7 +65,19 @@ impl syn::parse::Parse for BareIfClause {
5965
}
6066
}
6167

62-
/* ------------------------------------ */
68+
/* ----------------LetClause-------------------- */
69+
#[derive(Debug)]
70+
pub struct LetClause {
71+
pub let_expr: Expr,
72+
}
73+
74+
impl syn::parse::Parse for LetClause {
75+
fn parse(input: ParseStream) -> syn::Result<Self> {
76+
Ok(Self {
77+
let_expr: input.parse::<Expr>()?,
78+
})
79+
}
80+
}
6381

6482
#[cfg(test)]
6583
mod tests {

src/lazy_evaluation.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::iter_clause::{BareIfClause, ForInClause, IterClause};
1+
use crate::iter_clause::{BareIfClause, ForInClause, IterClause, LetClause};
22
use crate::mapping::{Mapping, MappingElse};
33

44
use quote::quote;
@@ -68,6 +68,7 @@ impl quote::ToTokens for IteratorRef {
6868
let IterClause {
6969
for_in_clause: ForInClause { pat, iterable },
7070
if_clause,
71+
let_clauses,
7172
} = iter_clause;
7273
info_container.depth += 1;
7374

@@ -89,6 +90,14 @@ impl quote::ToTokens for IteratorRef {
8990
None => quote! { true },
9091
};
9192

93+
let mut let_clauses: Vec<&LetClause> = let_clauses.iter().collect();
94+
while let Some(LetClause { let_expr }) = let_clauses.pop() {
95+
nested_code = quote! {
96+
#let_expr;
97+
#nested_code
98+
};
99+
}
100+
92101
nested_code = quote! {
93102
(#iterable)
94103
.into_iter()

src/main.rs

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -510,25 +510,66 @@ fn some_real_example_2() {
510510

511511
#[test]
512512
fn some() {
513-
use better_comprehension::iterator_ref;
514-
let vec_1 = ["123".to_string(),
515-
"456".to_string(),
516-
"789".to_string()];
517-
let vec_2 = ["ABC".to_string(),
518-
"DEF".to_string(),
519-
"GHI".to_string()];
520-
521-
let mut result3 = iterator_ref![
522-
(x.clone(), y.clone()) if x.contains("1") else (y.clone(), x.clone())
523-
for x in vec_1 if x.contains("1") || x.contains("7")
524-
for i in 1..=2
525-
for y in vec_2 if y.contains("D") || x.contains("3")];
526-
527-
// still alive
528-
println!("{:?}", vec_1);
529-
println!("{:?}", vec_2);
530-
531-
for _ in 0..=9 {
532-
println!("{:?}", result3.next());
533-
}
513+
#[derive(Debug, PartialEq, Eq)]
514+
struct Score {
515+
subject: &'static str,
516+
score: u8,
517+
}
518+
#[derive(Debug, PartialEq, Eq)]
519+
struct Student {
520+
name: String,
521+
age: u8,
522+
scores: Vec<Score>,
523+
}
524+
525+
let students_data = [
526+
Student {
527+
name: "Alice".to_string(),
528+
age: 20,
529+
scores: vec![
530+
Score {
531+
subject: "Math",
532+
score: 95,
533+
},
534+
Score {
535+
subject: "English",
536+
score: 88,
537+
},
538+
],
539+
},
540+
Student {
541+
name: "Bob".to_string(),
542+
age: 21,
543+
scores: vec![
544+
Score {
545+
subject: "Math",
546+
score: 78,
547+
},
548+
Score {
549+
subject: "English",
550+
score: 85,
551+
},
552+
],
553+
},
554+
];
555+
556+
let high_scores = b_tree_map![
557+
&student.name => high_scores
558+
for student in &students_data
559+
let high_scores = vector![
560+
score.subject
561+
for score in &student.scores if score.score >= 85
562+
]
563+
let _ = {
564+
println!("{}", high_scores.len());
565+
}
566+
];
567+
568+
assert_eq!(
569+
high_scores,
570+
BTreeMap::from([
571+
(&"Alice".to_string(), vec!["Math", "English"]),
572+
(&"Bob".to_string(), vec!["English"])
573+
])
574+
);
534575
}

0 commit comments

Comments
 (0)