1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
use crate::compiling::v1::assemble::prelude::*;

/// Compile a let expression.
impl Assemble for ast::ExprLet {
    fn assemble(&self, c: &mut Compiler<'_>, needs: Needs) -> CompileResult<Asm> {
        let span = self.span();
        log::trace!("ExprLet => {:?}", c.source.source(span));

        let load = |c: &mut Compiler, needs: Needs| {
            // NB: assignments "move" the value being assigned.
            self.expr.assemble(c, needs)?.apply(c)?;
            Ok(())
        };

        let false_label = c.asm.new_label("let_panic");

        if c.compile_pat(&self.pat, false_label, &load)? {
            c.diagnostics
                .let_pattern_might_panic(c.source_id, span, c.context());

            let ok_label = c.asm.new_label("let_ok");
            c.asm.jump(ok_label, span);
            c.asm.label(false_label)?;
            c.asm.push(
                Inst::Panic {
                    reason: runestick::PanicReason::UnmatchedPattern,
                },
                span,
            );

            c.asm.label(ok_label)?;
        }

        // If a value is needed for a let expression, it is evaluated as a unit.
        if needs.value() {
            c.asm.push(Inst::unit(), span);
        }

        Ok(Asm::top(span))
    }
}