Lines
65.6 %
Functions
31.43 %
Branches
100 %
//! `NOT` and `NULL?` predicates plus the shared `is_truthy` helper.
//! Both natives short-circuit at compile time on constant operands
//! and emit a wasm `i32_eqz` / `ref.is_null` check on runtime values.
use crate::ast::{Expr, WasmType};
use crate::compiler::context::CompileContext;
use crate::compiler::emit::FunctionEmitter;
use crate::compiler::expr::{compile_for_stack, eval_value, serialize_stack_to_output};
use crate::error::{Error, Result};
use crate::runtime::SymbolTable;
use super::shared::{bool_result, emit_bool};
fn is_truthy(expr: &Expr) -> bool {
!matches!(expr, Expr::Nil | Expr::Bool(false))
}
pub(super) fn not_fn(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
if args.len() != 1 {
return Err(Error::Arity {
name: "NOT".to_string(),
expected: 1,
actual: args.len(),
});
let val = eval_value(symbols, &args[0])?;
if val.wasm_type().is_some() {
return Ok(Expr::WasmRuntime(WasmType::Bool));
Ok(bool_result(!is_truthy(&val)))
pub(super) fn null_p(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
name: "NULL?".to_string(),
Ok(bool_result(matches!(val, Expr::Nil)))
pub(super) fn compile_not(
ctx: &mut CompileContext,
emit: &mut FunctionEmitter,
symbols: &mut SymbolTable,
args: &[Expr],
) -> Result<()> {
compile_not_to_stack(ctx, emit, symbols, args)?;
serialize_stack_to_output(ctx, emit, WasmType::Bool)?;
return Ok(());
emit_bool(ctx, emit, !is_truthy(&val));
Ok(())
pub(super) fn compile_null_p(
compile_null_p_to_stack(ctx, emit, symbols, args)?;
emit_bool(ctx, emit, matches!(val, Expr::Nil));
pub(super) fn compile_not_to_stack(
) -> Result<WasmType> {
match val.wasm_type() {
Some(WasmType::PairRef(_) | WasmType::StringRef | WasmType::EntityRef(_)) => {
compile_for_stack(ctx, emit, symbols, &args[0])?;
emit.ref_is_null();
return Ok(WasmType::Bool);
Some(WasmType::I32 | WasmType::Bool) => {
emit.i32_eqz();
_ => {}
emit.i32_const(i32::from(!is_truthy(&val)));
Ok(WasmType::Bool)
pub(super) fn compile_null_p_to_stack(
emit.i32_const(i32::from(matches!(val, Expr::Nil)));