Lines
62.26 %
Functions
15 %
Branches
100 %
//! `PAIR?` — true when the argument is a non-empty cons cell. A
//! compile-time list literal folds to a constant; a runtime `PairRef`
//! chain emits `ref.is_null` + `i32.eqz` (non-null ≡ a real cell). Nil
//! and atoms are never pairs.
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::super::comparison::bool_result;
fn is_const_pair(expr: &Expr) -> bool {
match expr {
Expr::Cons(_, _) => true,
Expr::List(elems) => !elems.is_empty(),
Expr::Quote(inner) => is_const_pair(inner),
_ => false,
}
pub(super) fn pair_p(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
if args.len() != 1 {
return Err(Error::Arity {
name: "PAIR?".to_string(),
expected: 1,
actual: args.len(),
});
let arg = eval_value(symbols, &args[0])?;
if matches!(arg.wasm_type(), Some(WasmType::PairRef(_))) {
return Ok(Expr::WasmRuntime(WasmType::Bool));
Ok(bool_result(is_const_pair(&arg)))
pub(super) fn compile_pair_p(
ctx: &mut CompileContext,
emit: &mut FunctionEmitter,
symbols: &mut SymbolTable,
args: &[Expr],
) -> Result<()> {
let ty = compile_pair_p_to_stack(ctx, emit, symbols, args)?;
serialize_stack_to_output(ctx, emit, ty)
pub(super) fn compile_pair_p_to_stack(
) -> Result<WasmType> {
let resolved = eval_value(symbols, &args[0])?;
if matches!(resolved.wasm_type(), Some(WasmType::PairRef(_))) {
compile_for_stack(ctx, emit, symbols, &args[0])?;
emit.ref_is_null();
emit.i32_eqz();
return Ok(WasmType::Bool);
emit.i32_const(i32::from(is_const_pair(&resolved)));
Ok(WasmType::Bool)