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

            
25
1292
pub(super) fn compile_begin_for_stack(
26
1292
    ctx: &mut CompileContext,
27
1292
    emit: &mut FunctionEmitter,
28
1292
    symbols: &mut SymbolTable,
29
1292
    args: &[Expr],
30
1292
) -> Result<WasmType> {
31
1292
    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
68
        emit.i32_const(0);
37
68
        return Ok(WasmType::Bool);
38
1224
    }
39
1224
    compile_body_for_stack(ctx, emit, symbols, args)
40
1292
}
41

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