1
//! `BEGIN` special form. Sequencing primitive — evaluates each body
2
//! form in order, returning the last value. Empty body collapses to
3
//! `nil`.
4

            
5
use crate::ast::{Expr, WasmType};
6
use crate::compiler::context::CompileContext;
7
use crate::compiler::emit::FunctionEmitter;
8
use crate::compiler::expr::{compile_body, compile_body_for_stack, compile_nil};
9
use crate::error::Result;
10
use crate::runtime::SymbolTable;
11

            
12
710
pub(super) fn compile_begin(
13
710
    ctx: &mut CompileContext,
14
710
    emit: &mut FunctionEmitter,
15
710
    symbols: &mut SymbolTable,
16
710
    args: &[Expr],
17
710
) -> Result<()> {
18
710
    if args.is_empty() {
19
        compile_nil(ctx, emit);
20
        return Ok(());
21
710
    }
22
710
    compile_body(ctx, emit, symbols, args)
23
710
}
24

            
25
1349
pub(super) fn compile_begin_for_stack(
26
1349
    ctx: &mut CompileContext,
27
1349
    emit: &mut FunctionEmitter,
28
1349
    symbols: &mut SymbolTable,
29
1349
    args: &[Expr],
30
1349
) -> Result<WasmType> {
31
1349
    if args.is_empty() {
32
        // Empty `(begin)` ≡ nil; push the falsy i31 value but type it `Bool`
33
        // so it serializes as Nil (not Number(0)) and agrees with the eval
34
        // mirror (`begin_form` → `Expr::Nil`), keeping a runtime-IF branch
35
        // homogeneous.
36
71
        emit.i32_const(0);
37
71
        return Ok(WasmType::Bool);
38
1278
    }
39
1278
    compile_body_for_stack(ctx, emit, symbols, args)
40
1349
}
41

            
42
1491
pub(super) fn begin_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
43
1491
    if args.is_empty() {
44
71
        return Ok(Expr::Nil);
45
1420
    }
46
1420
    super::super::binding::eval_body(symbols, args)
47
1491
}