• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mattwparas / steel / 17772690385

16 Sep 2025 04:36PM UTC coverage: 43.331% (+0.04%) from 43.289%
17772690385

Pull #519

github

web-flow
Merge 98d4fd22c into 3c10433b9
Pull Request #519: fix a bunch more clippy lints

56 of 123 new or added lines in 30 files covered. (45.53%)

8 existing lines in 3 files now uncovered.

12416 of 28654 relevant lines covered (43.33%)

2985398.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.08
/crates/steel-core/src/compiler/passes/begin.rs
1
use smallvec::SmallVec;
2
use steel_parser::{
3
    ast::{Define, If, Let, Macro, Quote, Require, Return, SyntaxRules, Vector},
4
    tokens::IntLiteral,
5
};
6

7
use crate::parser::{
8
    ast::{Atom, Begin, ExprKind, LambdaFunction, List, Set},
9
    parser::SyntaxObject,
10
    visitors::VisitorMutRef,
11
};
12
use crate::parser::{interner::InternedString, tokens::TokenType};
13

14
#[cfg(feature = "profiling")]
15
use std::time::Instant;
16

17
use super::{Folder, VisitorMutRefUnit, VisitorMutUnit};
18

19
pub(crate) struct CheckDefinesAreInLegalPositions {
20
    depth: usize,
21
}
22
impl VisitorMutRef for CheckDefinesAreInLegalPositions {
23
    type Output = crate::rvals::Result<()>;
24

25
    #[inline]
26
    fn visit_lambda_function(&mut self, lambda_function: &mut LambdaFunction) -> Self::Output {
269,902✔
27
        for var in &mut lambda_function.args {
890,440✔
28
            self.visit(var)?;
930,807✔
29
        }
30
        self.depth += 1;
269,902✔
31
        self.visit(&mut lambda_function.body)?;
×
32
        self.depth -= 1;
269,902✔
33
        Ok(())
×
34
    }
35

36
    #[inline]
37
    fn visit_if(&mut self, f: &mut If) -> Self::Output {
131,500✔
38
        self.depth += 1;
131,500✔
39
        self.visit(&mut f.test_expr)?;
394,500✔
40
        self.visit(&mut f.then_expr)?;
131,500✔
41
        self.visit(&mut f.else_expr)?;
131,500✔
42
        self.depth -= 1;
131,500✔
43

44
        Ok(())
×
45
    }
46

47
    #[inline]
48
    fn visit_let(&mut self, l: &mut Let) -> Self::Output {
8,462✔
49
        self.depth += 1;
8,462✔
50

51
        for x in l.bindings.iter_mut() {
42,306✔
52
            self.visit(&mut x.1)?;
76,146✔
53
        }
54

55
        self.visit(&mut l.body_expr)?;
8,462✔
56
        self.depth -= 1;
8,462✔
57

58
        Ok(())
×
59
    }
60

61
    #[inline]
62
    fn visit_define(&mut self, define: &mut Define) -> Self::Output {
628,601✔
63
        if self.depth != 0 {
628,601✔
64
            crate::stop!(BadSyntax => "Define cannot exist except at the top level, unless within another lexical context or begin expression"; define.location.span);
×
65
        }
66

67
        self.visit(&mut define.name)?;
×
68
        self.visit(&mut define.body)?;
628,601✔
69

70
        Ok(())
628,601✔
71
    }
72

73
    fn visit_begin(&mut self, begin: &mut Begin) -> Self::Output {
64,076✔
74
        for expr in &mut begin.exprs {
1,501,568✔
75
            self.visit(expr)?;
2,156,238✔
76
        }
77

78
        Ok(())
64,076✔
79
    }
80

81
    fn visit(&mut self, expr: &mut ExprKind) -> Self::Output {
7,647,464✔
82
        match expr {
7,647,464✔
83
            ExprKind::If(f) => self.visit_if(f),
526,000✔
84
            ExprKind::Define(d) => self.visit_define(d),
2,514,404✔
85
            ExprKind::LambdaFunction(l) => self.visit_lambda_function(l),
1,079,608✔
86
            ExprKind::Begin(b) => self.visit_begin(b),
256,304✔
87
            ExprKind::Return(r) => self.visit_return(r),
1,800✔
88
            ExprKind::Quote(q) => self.visit_quote(q),
3,359,864✔
89
            ExprKind::Macro(m) => self.visit_macro(m),
×
90
            ExprKind::Atom(a) => self.visit_atom(a),
4,051,979✔
91
            ExprKind::List(l) => self.visit_list(l),
6,448,788✔
92
            ExprKind::SyntaxRules(s) => self.visit_syntax_rules(s),
×
93
            ExprKind::Set(s) => self.visit_set(s),
160,052✔
94
            ExprKind::Require(r) => self.visit_require(r),
×
95
            ExprKind::Let(l) => self.visit_let(l),
33,848✔
96
            ExprKind::Vector(v) => self.visit_vector(v),
1,272✔
97
        }
98
    }
99

100
    #[inline]
101
    fn visit_return(&mut self, r: &mut Return) -> Self::Output {
450✔
102
        self.visit(&mut r.expr)?;
1,350✔
103
        Ok(())
450✔
104
    }
105

106
    #[inline]
107
    fn visit_quote(&mut self, _quote: &mut Quote) -> Self::Output {
839,966✔
108
        // self.visit(&mut quote.expr)?;
109
        Ok(())
839,966✔
110
    }
111

112
    #[inline]
113
    fn visit_macro(&mut self, _m: &mut Macro) -> Self::Output {
×
114
        Ok(())
×
115
    }
116

117
    #[inline]
118
    fn visit_atom(&mut self, _a: &mut Atom) -> Self::Output {
4,051,979✔
119
        Ok(())
4,051,979✔
120
    }
121

122
    #[inline]
123
    fn visit_list(&mut self, l: &mut List) -> Self::Output {
1,612,197✔
124
        for expr in &mut l.args {
10,541,017✔
125
            self.visit(expr)?;
13,393,230✔
126
        }
127
        Ok(())
1,612,197✔
128
    }
129

130
    #[inline]
131
    fn visit_syntax_rules(&mut self, _l: &mut SyntaxRules) -> Self::Output {
×
132
        Ok(())
×
133
    }
134

135
    #[inline]
136
    fn visit_set(&mut self, s: &mut Set) -> Self::Output {
40,013✔
137
        self.visit(&mut s.variable)?;
120,039✔
138
        self.visit(&mut s.expr)?;
40,013✔
139
        Ok(())
40,013✔
140
    }
141

142
    #[inline]
143
    fn visit_require(&mut self, _s: &mut Require) -> Self::Output {
×
144
        Ok(())
×
145
    }
146

147
    #[inline]
148
    fn visit_vector(&mut self, v: &mut Vector) -> Self::Output {
318✔
149
        if v.bytes {
318✔
150
            return Ok(());
76✔
151
        }
152

153
        for arg in &mut v.args {
1,546✔
154
            self.visit(arg)?;
1,956✔
155
        }
156

157
        Ok(())
242✔
158
    }
159
}
160

161
pub(crate) struct FlattenBegin {}
162
impl FlattenBegin {
163
    pub(crate) fn flatten(expr: &mut ExprKind) {
155,047✔
164
        FlattenBegin {}.visit(expr)
165
    }
166
}
167

168
impl VisitorMutRefUnit for FlattenBegin {
169
    fn visit(&mut self, expr: &mut ExprKind) {
12,470,498✔
170
        match expr {
12,470,498✔
171
            ExprKind::If(f) => self.visit_if(f),
695,532✔
172
            ExprKind::Define(d) => self.visit_define(d),
4,303,788✔
173
            ExprKind::LambdaFunction(l) => self.visit_lambda_function(l),
1,251,224✔
174
            ExprKind::Begin(begin) => {
138,880✔
175
                for expr in begin.exprs.iter_mut() {
1,527,872✔
176
                    self.visit(expr);
177
                }
178

179
                if begin.exprs.len() == 1 {
138,880✔
180
                    *expr = std::mem::take(&mut begin.exprs).into_iter().next().unwrap();
163,790✔
181

182
                    return;
32,758✔
183
                }
184

185
                let begin_exprs = std::mem::take(&mut begin.exprs);
186

187
                let mut flattened_exprs = Vec::with_capacity(begin_exprs.len());
188

189
                for expr in begin_exprs {
2,540,830✔
190
                    if let ExprKind::Begin(mut b) = expr {
5,949✔
191
                        flattened_exprs.append(&mut b.exprs)
192
                    } else {
193
                        flattened_exprs.push(expr);
2,422,810✔
194
                    }
195
                }
196

197
                begin.exprs = flattened_exprs;
198

UNCOV
199
                if begin.exprs.len() == 1 {
×
200
                    *expr = std::mem::take(&mut begin.exprs).into_iter().next().unwrap();
×
201
                }
202
            }
203
            ExprKind::Return(r) => self.visit_return(r),
2,588✔
204
            ExprKind::Quote(q) => self.visit_quote(q),
4,980,048✔
205
            ExprKind::Macro(m) => self.visit_macro(m),
×
206
            ExprKind::Atom(a) => self.visit_atom(a),
7,100,859✔
207
            ExprKind::List(l) => self.visit_list(l),
9,458,420✔
208
            ExprKind::SyntaxRules(s) => self.visit_syntax_rules(s),
×
209
            ExprKind::Set(s) => self.visit_set(s),
180,972✔
210
            ExprKind::Require(r) => self.visit_require(r),
×
211
            ExprKind::Let(l) => self.visit_let(l),
47,644✔
212
            ExprKind::Vector(v) => self.visit_vector(v),
2,820✔
213
        }
214
    }
215
}
216

217
pub fn flatten_begins_and_expand_defines(
22,945✔
218
    exprs: Vec<ExprKind>,
219
) -> crate::rvals::Result<Vec<ExprKind>> {
220
    #[cfg(feature = "profiling")]
221
    let flatten_begins_and_expand_defines_time = Instant::now();
222

223
    let res = exprs
45,890✔
224
        .into_iter()
225
        .map(|mut x| {
140,408✔
226
            FlattenBegin::flatten(&mut x);
234,926✔
227
            x
117,463✔
228
        })
229
        .map(ConvertDefinesToLets::convert_defines)
22,945✔
230
        .map(|mut x| {
140,408✔
231
            let mut checker = CheckDefinesAreInLegalPositions { depth: 0 };
234,926✔
232
            checker.visit(&mut x)?;
352,389✔
233
            Ok(x)
117,463✔
234
        })
235
        .collect();
236

237
    #[cfg(feature = "profiling")]
238
    log::debug!(
239
        target: "pipeline_time",
240
        "Flatten begins and expand defines time: {:?}",
241
        flatten_begins_and_expand_defines_time.elapsed()
242
    );
243
    res
22,945✔
244
}
245

246
struct DefinedVars {
247
    defined_identifiers: smallvec::SmallVec<[InternedString; 32]>,
248
    output: bool,
249
}
250

251
impl DefinedVars {
252
    fn new() -> Self {
68,696✔
253
        DefinedVars {
254
            defined_identifiers: smallvec::SmallVec::default(),
68,696✔
255
            output: false,
256
        }
257
    }
258

259
    fn insert(&mut self, name: InternedString) {
28,602✔
260
        self.defined_identifiers.push(name);
85,806✔
261
    }
262

263
    fn check_output(&mut self) -> bool {
23,406✔
264
        let output = self.output;
46,812✔
265
        self.output = false;
23,406✔
266
        output
23,406✔
267
    }
268
}
269

270
impl VisitorMutUnit for DefinedVars {
271
    fn visit_atom(&mut self, a: &Atom) {
141,996✔
272
        if let TokenType::Identifier(ident) = &a.syn.ty {
264,396✔
273
            self.output = self.output || self.defined_identifiers.contains(ident);
72,287✔
274
        }
275
    }
276
}
277

278
struct ConvertDefinesToLets {
279
    depth: usize,
280
}
281

282
impl ConvertDefinesToLets {
283
    fn new() -> Self {
117,463✔
284
        Self { depth: 0 }
285
    }
286

287
    fn convert_defines(expr: ExprKind) -> ExprKind {
117,463✔
288
        ConvertDefinesToLets::new().visit(expr)
352,389✔
289
    }
290
}
291

292
// TODO: Replace this with mutation!
293
impl Folder for ConvertDefinesToLets {
294
    #[inline]
295
    fn visit_lambda_function(&mut self, mut lambda_function: Box<LambdaFunction>) -> ExprKind {
269,902✔
296
        self.depth += 1;
269,902✔
297
        lambda_function.body = self.visit(lambda_function.body);
1,079,608✔
298
        self.depth -= 1;
269,902✔
299
        ExprKind::LambdaFunction(lambda_function)
269,902✔
300
    }
301

302
    #[inline]
303
    fn visit_let(&mut self, mut l: Box<steel_parser::ast::Let>) -> ExprKind {
8,462✔
304
        let mut visited_bindings = Vec::new();
16,924✔
305

306
        self.depth += 1;
8,462✔
307

308
        for (binding, expr) in l.bindings {
59,226✔
309
            visited_bindings.push((self.visit(binding), self.visit(expr)));
×
310
        }
311

312
        l.bindings = visited_bindings;
16,924✔
313
        l.body_expr = self.visit(l.body_expr);
33,848✔
314

315
        self.depth -= 1;
8,462✔
316

317
        ExprKind::Let(l)
8,462✔
318
    }
319

320
    // TODO
321
    #[inline]
322
    fn visit_begin(&mut self, mut begin: Box<Begin>) -> ExprKind {
75,169✔
323
        if self.depth > 0 {
75,169✔
324
            match convert_exprs_to_let(begin) {
68,696✔
325
                ExprKind::Begin(mut b) => {
57,603✔
326
                    b.exprs = b.exprs.into_iter().map(|e| self.visit(e)).collect();
837,708✔
327
                    ExprKind::Begin(b)
57,603✔
328
                }
329
                ExprKind::List(mut l) => {
11,093✔
330
                    l.args = l.args.into_iter().map(|x| self.visit(x)).collect();
132,415✔
331
                    ExprKind::List(l)
11,093✔
332
                }
333
                ExprKind::Let(mut l) => {
×
334
                    let mut visited_bindings = Vec::new();
×
335

336
                    for (binding, expr) in l.bindings {
×
337
                        visited_bindings.push((self.visit(binding), self.visit(expr)));
×
338
                    }
339

340
                    l.bindings = visited_bindings;
×
341
                    l.body_expr = self.visit(l.body_expr);
×
342

343
                    ExprKind::Let(l)
×
344
                }
345
                other => panic!("Something went wrong in define conversion, found: {other:?}"),
×
346
            }
347
        } else {
348
            // println!("Ignoring begin");
349
            begin.exprs = begin.exprs.into_iter().map(|e| self.visit(e)).collect();
1,613,018✔
350
            ExprKind::Begin(begin)
×
351
        }
352
    }
353
}
354

355
#[derive(PartialEq, Debug)]
356
enum ExpressionType {
357
    DefineConst(InternedString),
358
    DefineFlat(InternedString),
359
    DefineFlatStar(InternedString),
360
    DefineFunction(InternedString),
361
    Expression,
362
}
363

364
impl ExpressionType {
365
    fn is_expression(&self) -> bool {
199,114✔
366
        matches!(self, ExpressionType::Expression)
212,747✔
367
    }
368

369
    fn is_atom(t: &SyntaxObject) -> bool {
767✔
370
        matches!(
567✔
371
            t.ty,
767✔
372
            TokenType::BooleanLiteral(_)
373
                | TokenType::Number(_)
374
                | TokenType::StringLiteral(_)
375
                | TokenType::CharacterLiteral(_)
376
        )
377
    }
378

379
    fn is_constant(expr: &ExprKind) -> bool {
12,758✔
380
        match expr {
12,758✔
381
            ExprKind::Atom(Atom { syn, .. }) => Self::is_atom(syn),
767✔
382
            _ => false,
11,991✔
383
        }
384
    }
385

386
    fn generate_expression_types(exprs: &[ExprKind]) -> Vec<ExpressionType> {
68,696✔
387
        let mut expression_types = Vec::with_capacity(exprs.len());
274,784✔
388
        let mut defined_idents = DefinedVars::new();
137,392✔
389

390
        for expr in exprs {
520,482✔
391
            match expr {
392
                ExprKind::Define(d) => {
28,602✔
393
                    let name = d
394
                        .name
395
                        .atom_identifier_or_else(|| {})
×
396
                        .expect("Define without a legal name");
397

398
                    defined_idents.insert(*name);
399

400
                    match &d.body {
401
                        ExprKind::LambdaFunction(_) => {
5,196✔
402
                            expression_types.push(ExpressionType::DefineFunction(*name));
5,196✔
403
                        }
404
                        _ => {
405
                            defined_idents.visit(&d.body);
70,218✔
406
                            if defined_idents.check_output() {
57,460✔
407
                                expression_types.push(ExpressionType::DefineFlatStar(*name));
21,296✔
408
                            } else if Self::is_constant(&d.body) {
23,606✔
409
                                expression_types.push(ExpressionType::DefineConst(*name));
400✔
410
                            } else {
411
                                expression_types.push(ExpressionType::DefineFlat(*name));
12,558✔
412
                            }
413
                        }
414
                    }
415
                }
416
                _ => expression_types.push(ExpressionType::Expression),
591,873✔
417
            }
418
        }
419

420
        // println!("Expression types: {:?}", expression_types);
421

422
        expression_types
68,696✔
423
    }
424
}
425

426
fn set(var: ExprKind, expr: ExprKind) -> ExprKind {
5,616✔
427
    ExprKind::Set(Box::new(Set::new(
16,848✔
428
        var,
11,232✔
429
        expr,
11,232✔
430
        SyntaxObject::default(TokenType::Set),
5,616✔
431
    )))
432
}
433

434
fn apply_ident(func: ExprKind) -> ExprKind {
222✔
435
    ExprKind::List(List::new(vec![func]))
444✔
436
}
437

438
fn convert_exprs_to_let(begin: Box<Begin>) -> ExprKind {
68,696✔
439
    // let defines = collect_defines_from_current_scope(&exprs);
440

441
    let expression_types = ExpressionType::generate_expression_types(&begin.exprs);
206,088✔
442

443
    // Go ahead and quit if there are only expressions here
444
    if expression_types.iter().all(|x| x.is_expression()) {
526,054✔
445
        return ExprKind::Begin(begin);
57,410✔
446
    }
447

448
    if !expression_types
449
        .iter()
450
        .any(|x| matches!(x, ExpressionType::DefineFunction(_)))
36,595✔
451
    {
452
        // let starting_iter = ExprKind::atom("void".to_string())
453

454
        // TODO: last expression needs to be something, otherwise this doesn't work
455
        // if let Some(last) = expression_types.last() {
456
        //     if !last.is_expression() {}
457
        // }
458

459
        // println!("IN HERE");
460
        // println!("Expression_types")
461

462
        return begin
8,939✔
463
            .exprs
8,939✔
464
            .into_iter()
465
            .rev()
466
            .reduce(|accum, expr| {
25,292✔
467
                // println!("Accum: {:?}, Expr: {:?}", accum, expr);
468

469
                match expr {
25,292✔
470
                    ExprKind::Define(d) => {
22,791✔
471
                        // let constructed_function =
472

473
                        let constructed_function = ExprKind::LambdaFunction(
474
                            LambdaFunction::new(
475
                                vec![d.name],
476
                                accum,
477
                                SyntaxObject::default(TokenType::Lambda),
478
                            )
479
                            .into(),
480
                        );
481

482
                        ExprKind::List(List::new(vec![constructed_function, d.body]))
483
                    }
484
                    other => ExprKind::Begin(Box::new(Begin::new(
10,004✔
485
                        vec![other, accum],
10,004✔
486
                        SyntaxObject::default(TokenType::Begin),
2,501✔
487
                    ))),
488
                }
489
            })
490
            .expect("Empty expression");
491

492
        // return todo!();
493
    }
494

495
    let mut exprs = begin.exprs.clone();
7,041✔
496

497
    // let mut last_expression = expression_types.len();
498

499
    let idx = expression_types
4,694✔
500
        .iter()
501
        .rev()
502
        .position(|x| !x.is_expression())
11,913✔
503
        .expect("Convert exprs to let in define conversion found no trailing expressions in begin");
504

505
    // println!("Last expression index: {:?}", idx);
506

507
    let idx = expression_types.len() - 1 - idx;
4,694✔
508

509
    let mut body = exprs.split_off(idx + 1);
9,388✔
510

511
    // These are going to be the
512
    let args = exprs
4,694✔
513
        .iter()
514
        .map(|x| {
8,728✔
515
            if let ExprKind::Define(d) = x {
12,192✔
516
                d.body.clone()
517
            } else {
518
                x.clone()
1,140✔
519
            }
520
        })
521
        .collect::<SmallVec<[_; 8]>>();
522

523
    // This corresponds to the (let ((apple ..) (banana ..) (cucumber ..)))
524
    //                               ^^^^^^     ^^^^^^^      ^^^^^^^^
525
    let mut top_level_arguments: Vec<ExprKind> = Vec::with_capacity(idx + 1);
9,388✔
526

527
    // This corresponds to the set expressions
528
    // (set! apple #####apple0)
529
    // (set! banana #####banana1)
530
    // (set! cucumber #####cucumber1)
531
    let mut set_expressions: Vec<ExprKind> = Vec::with_capacity(idx + 1);
9,388✔
532

533
    // corresponds to #####apple0, #####banana1, #####cucumber1, etc
534
    let mut bound_names: Vec<ExprKind> = Vec::with_capacity(idx + 1);
9,388✔
535

536
    // TODO - check that the last expression does not contain any usages of the constant?
537
    // if expression_types[0..idx + 1]
538
    //     .iter()
539
    //     .all(|x| matches!(x, ExpressionType::DefineConst(_)))
540
    // {
541
    //     return ExprKind::Begin(Begin::new(body, begin.location));
542
    // }
543

544
    // Top level application with dummy arguments that will immediately get overwritten
545
    let mut top_level_dummy_args = Vec::with_capacity(idx + 1);
7,041✔
546

547
    let mut new_args = Vec::with_capacity(idx + 1);
7,041✔
548

549
    // println!("{:#?}", expression_types);
550

551
    // TODO:
552
    // If there are functions at all, go through this weird path
553
    // Otherwise, we should do the following transformation:
554
    //
555
    // If there are no functions at all, just do a series of lets, similar to let*
556

557
    // TODO: Move this up so we don't have to use raw_exprs anymore
558

559
    for ((i, expression), arg) in expression_types[0..idx + 1].iter().enumerate().zip(args) {
30,878✔
560
        match expression {
6,381✔
561
            ExpressionType::DefineFunction(name) => {
5,196✔
562
                if let ExprKind::Define(d) = &exprs[i] {
15,588✔
563
                    top_level_arguments.push(d.name.clone());
25,980✔
564
                    top_level_dummy_args.push(ExprKind::Atom(Atom::new(SyntaxObject::default(
31,176✔
565
                        IntLiteral::Small(0).into(),
10,392✔
566
                    ))));
567
                    let name_prime = ExprKind::atom(compact_str::format_compact!(
20,784✔
568
                        "_____{}{}",
10,392✔
569
                        name.resolve(),
15,588✔
570
                        i
5,196✔
571
                    ));
572
                    let set_expr = set(d.name.clone(), name_prime.clone());
36,372✔
573
                    bound_names.push(name_prime);
20,784✔
574
                    set_expressions.push(set_expr);
20,784✔
575
                    new_args.push(arg);
10,392✔
576
                } else {
577
                    panic!("expected define, found: {}", &exprs[i]);
×
578
                };
579

580
                // let name = Atom::new(SyntaxObject::new)
581
            }
582
            ExpressionType::DefineFlat(name) => {
198✔
583
                if let ExprKind::Define(d) = &exprs[i] {
594✔
584
                    top_level_arguments.push(d.name.clone());
990✔
585
                    top_level_dummy_args.push(ExprKind::Atom(Atom::new(SyntaxObject::default(
1,188✔
586
                        IntLiteral::Small(0).into(),
396✔
587
                    ))));
588
                    let name_prime = ExprKind::atom(compact_str::format_compact!(
792✔
589
                        "_____{}{}",
396✔
590
                        name.resolve(),
594✔
591
                        i
198✔
592
                    ));
593
                    let set_expr = set(d.name.clone(), name_prime.clone());
1,386✔
594
                    bound_names.push(name_prime);
792✔
595
                    set_expressions.push(set_expr);
792✔
596
                    new_args.push(arg);
396✔
597
                } else {
598
                    panic!("expected define, found: {}", &exprs[i]);
×
599
                };
600
            }
601
            ExpressionType::DefineConst(_name) => {
195✔
602
                if let ExprKind::Define(d) = &exprs[i] {
195✔
603
                    top_level_dummy_args.push(arg);
604
                    top_level_arguments.push(d.name.clone());
605
                    // top_level_arguments.push(d.name.clone());
606
                    // let name_prime = atom("#####".to_string() + name + i.to_string().as_str());
607
                    // let set_expr = set(d.name.clone(), name_prime.clone());
608
                    // bound_names.push(name_prime);
609
                    // set_expressions.push(set_expr);
610
                } else {
611
                    panic!("expected define, found: {}", &exprs[i]);
×
612
                };
613
            }
614
            ExpressionType::DefineFlatStar(name) => {
222✔
615
                if let ExprKind::Define(d) = &exprs[i] {
666✔
616
                    top_level_arguments.push(d.name.clone());
1,110✔
617
                    top_level_dummy_args.push(ExprKind::Atom(Atom::new(SyntaxObject::default(
1,332✔
618
                        IntLiteral::Small(0).into(),
444✔
619
                    ))));
620
                    let name_prime = ExprKind::atom(compact_str::format_compact!(
888✔
621
                        "_____{}{}",
444✔
622
                        name.resolve(),
666✔
623
                        i
222✔
624
                    ));
625

626
                    // Make this a (set! x (x'))
627
                    // Applying the function
628
                    let set_expr = set(d.name.clone(), apply_ident(name_prime.clone()));
1,776✔
629

630
                    // Set this to be an empty function (lambda () <expr>)
631
                    new_args.push(
666✔
632
                        LambdaFunction::new(
444✔
633
                            Vec::new(),
444✔
634
                            arg.clone(),
666✔
635
                            SyntaxObject::default(TokenType::Lambda),
666✔
636
                        )
637
                        .into(),
444✔
638
                    );
639

640
                    bound_names.push(name_prime);
888✔
641
                    set_expressions.push(set_expr);
444✔
642
                } else {
643
                    panic!("expected define, found: {}", &exprs[i]);
×
644
                };
645
            }
646
            // TODO: Move this down, don't put it with the lets, put it down in order with the set expressions
647
            // That way we're not at risk of accidentally goofing up the ordering of the expressions.
648
            // If will _only_ go in the right order of assignment
649
            ExpressionType::Expression => {
650
                // TODO: This is definitly not right
651
                // let expr = atom("#####define-conversion".to_string() + i.to_string().as_str());
652
                // top_level_dummy_args.push(ExprKind::Atom(Atom::new(SyntaxObject::default(
653
                //     TokenType::IntegerLiteral(123),
654
                // ))));
655

656
                // // This also gets bound in the inner function for now
657
                // bound_names.push(expr.clone());
658

659
                // top_level_arguments.push(expr);
660
                // new_args.push(arg);
661

662
                set_expressions.push(arg)
1,710✔
663
            }
664
        }
665
    }
666

667
    // // Append the body instructions to the set!
668
    set_expressions.append(&mut body);
2,347✔
669

670
    let inner_lambda = LambdaFunction::new(
671
        bound_names,
672
        ExprKind::Begin(Box::new(Begin::new(
673
            set_expressions,
674
            SyntaxObject::default(TokenType::Begin),
675
        ))),
676
        SyntaxObject::default(TokenType::Lambda),
677
    );
678

679
    new_args.insert(0, ExprKind::LambdaFunction(Box::new(inner_lambda)));
680

681
    let inner_application = ExprKind::List(List::new(new_args));
682

683
    let outer_lambda = LambdaFunction::new(
684
        top_level_arguments,
685
        inner_application,
686
        SyntaxObject::default(TokenType::Lambda),
687
    );
688

689
    top_level_dummy_args.insert(0, ExprKind::LambdaFunction(Box::new(outer_lambda)));
690

691
    ExprKind::List(List::new(top_level_dummy_args))
692

693
    // TODO: This is the real transformation that needs to take place once lets are fixed
694
    // follow-up - let rec is going to be completely broken
695

696
    // let pairs = bound_names
697
    //     .into_iter()
698
    //     .zip(new_args.into_iter())
699
    //     .collect::<Vec<_>>();
700

701
    // let inner_let = Let::new(
702
    //     pairs,
703
    //     ExprKind::Begin(Begin::new(
704
    //         set_expressions,
705
    //         SyntaxObject::default(TokenType::Begin),
706
    //     )),
707
    //     SyntaxObject::default(TokenType::Let),
708
    // );
709

710
    // let outer_pairs = top_level_arguments
711
    //     .into_iter()
712
    //     .zip(top_level_dummy_args.into_iter())
713
    //     .collect::<Vec<_>>();
714

715
    // let outer_let = Let::new(
716
    //     outer_pairs,
717
    //     ExprKind::Let(Box::new(inner_let)),
718
    //     SyntaxObject::default(TokenType::Let),
719
    // );
720

721
    // let output = ExprKind::Let(Box::new(outer_let));
722

723
    // println!("-----------------");
724
    // println!("{}", output.to_pretty(60));
725

726
    // output
727
}
728

729
#[cfg(test)]
730
mod flatten_begin_test {
731

732
    use super::*;
733
    use crate::parser::ast::ExprKind;
734
    use crate::parser::ast::{Atom, Begin, List};
735

736
    use crate::parser::parser::SyntaxObject;
737
    use crate::parser::tokens::TokenType;
738
    use crate::parser::tokens::TokenType::*;
739

740
    // #[test]
741
    // fn defines_translates_to_simple_let() {
742
    //     let expr = r#"
743
    //     (lambda ()
744
    //         (begin
745
    //             (define x 10)
746
    //             (define y 20)
747
    //             (define z 30)
748
    //             (+ x y z)))"#;
749

750
    //     let expected = r#"
751
    //     (lambda () ((lambda (x y z) ((lambda () (begin (+ x y z))))) 10 20 30))
752
    //     "#;
753

754
    //     let parsed = Parser::parse(expr).unwrap();
755
    //     let expected_parsed = Parser::parse(expected).unwrap();
756

757
    //     let result = flatten_begins_and_expand_defines(parsed);
758

759
    //     assert_eq!(result, expected_parsed);
760
    // }
761

762
    fn atom(ident: &str) -> ExprKind {
763
        ExprKind::Atom(Atom::new(SyntaxObject::default(Identifier(ident.into()))))
764
    }
765

766
    fn int(num: isize) -> ExprKind {
767
        ExprKind::Atom(Atom::new(SyntaxObject::default(
768
            IntLiteral::Small(num).into(),
769
        )))
770
    }
771

772
    #[test]
773
    fn basic_flatten_one_level() {
774
        let mut expr = ExprKind::Begin(Box::new(Begin::new(
775
            vec![
776
                ExprKind::Begin(Box::new(Begin::new(
777
                    vec![ExprKind::List(List::new(vec![
778
                        atom("+"),
779
                        atom("x"),
780
                        int(10),
781
                    ]))],
782
                    SyntaxObject::default(TokenType::Begin),
783
                ))),
784
                ExprKind::List(List::new(vec![atom("+"), atom("y"), int(20)])),
785
                ExprKind::List(List::new(vec![atom("+"), atom("z"), int(30)])),
786
            ],
787
            SyntaxObject::default(TokenType::Begin),
788
        )));
789

790
        let expected = ExprKind::Begin(Box::new(Begin::new(
791
            vec![
792
                ExprKind::List(List::new(vec![atom("+"), atom("x"), int(10)])),
793
                ExprKind::List(List::new(vec![atom("+"), atom("y"), int(20)])),
794
                ExprKind::List(List::new(vec![atom("+"), atom("z"), int(30)])),
795
            ],
796
            SyntaxObject::default(TokenType::Begin),
797
        )));
798

799
        FlattenBegin::flatten(&mut expr);
800

801
        assert_eq!(expr, expected);
802
    }
803

804
    #[test]
805
    fn basic_flatten_multiple_levels() {
806
        let mut expr = ExprKind::Begin(Box::new(Begin::new(
807
            vec![
808
                ExprKind::Begin(Box::new(Begin::new(
809
                    vec![ExprKind::List(List::new(vec![
810
                        atom("+"),
811
                        atom("x"),
812
                        int(10),
813
                    ]))],
814
                    SyntaxObject::default(TokenType::Begin),
815
                ))),
816
                ExprKind::Begin(Box::new(Begin::new(
817
                    vec![ExprKind::List(List::new(vec![
818
                        atom("+"),
819
                        atom("y"),
820
                        int(20),
821
                    ]))],
822
                    SyntaxObject::default(TokenType::Begin),
823
                ))),
824
                ExprKind::Begin(Box::new(Begin::new(
825
                    vec![ExprKind::List(List::new(vec![
826
                        atom("+"),
827
                        atom("z"),
828
                        int(30),
829
                    ]))],
830
                    SyntaxObject::default(TokenType::Begin),
831
                ))),
832
            ],
833
            SyntaxObject::default(TokenType::Begin),
834
        )));
835

836
        let expected = ExprKind::Begin(Box::new(Begin::new(
837
            vec![
838
                ExprKind::List(List::new(vec![atom("+"), atom("x"), int(10)])),
839
                ExprKind::List(List::new(vec![atom("+"), atom("y"), int(20)])),
840
                ExprKind::List(List::new(vec![atom("+"), atom("z"), int(30)])),
841
            ],
842
            SyntaxObject::default(TokenType::Begin),
843
        )));
844

845
        FlattenBegin::flatten(&mut expr);
846

847
        assert_eq!(expr, expected);
848
    }
849
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc