Lines
64.18 %
Functions
10 %
Branches
100 %
use crate::ast::{Expr, LambdaParams};
use crate::error::{Error, Result};
use crate::runtime::{Symbol, SymbolKind, SymbolTable};
use super::super::context::CompileContext;
use super::super::emit::FunctionEmitter;
use super::super::expr::compile_body;
use super::binding::{eval_body, parse_param_list};
struct LabelDef {
name: String,
params: Vec<String>,
body: Expr,
}
fn parse_labels_defs(args: &[Expr]) -> Result<(Vec<LabelDef>, &[Expr])> {
if args.len() < 2 {
return Err(Error::Compile(
"LABELS requires a definitions list and at least one body form".to_string(),
));
let defs_list = args[0].as_list().ok_or_else(|| {
Error::Compile(format!(
"LABELS: expected definitions list, got {:?}",
args[0]
))
})?;
let defs = defs_list
.iter()
.map(|def| {
let elems = def.as_list().ok_or_else(|| {
Error::Compile(format!("LABELS: expected function definition, got {def:?}"))
if elems.len() < 3 {
"LABELS: each definition needs a name, params, and body".to_string(),
let name = elems[0]
.as_symbol()
.ok_or_else(|| {
"LABELS: expected function name, got {:?}",
elems[0]
})?
.to_string();
let params = parse_param_list("LABELS", &elems[1])?;
let body = if elems.len() == 3 {
elems[2].clone()
} else {
let mut forms = Vec::with_capacity(elems.len() - 1);
forms.push(Expr::Symbol("BEGIN".to_string()));
forms.extend_from_slice(&elems[2..]);
Expr::List(forms)
};
Ok(LabelDef { name, params, body })
})
.collect::<Result<Vec<_>>>()?;
Ok((defs, &args[1..]))
fn define_labels(symbols: &mut SymbolTable, defs: Vec<LabelDef>) -> SymbolTable {
let mut local = symbols.clone();
for def in defs {
let lambda = Expr::Lambda(LambdaParams::simple(def.params), Box::new(def.body));
local.define(Symbol::new(&def.name, SymbolKind::Function).with_function(lambda));
local
pub(super) fn labels_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
let (defs, body) = parse_labels_defs(args)?;
let mut local = define_labels(symbols, defs);
eval_body(&mut local, body)
pub(super) fn compile_labels(
ctx: &mut CompileContext,
emit: &mut FunctionEmitter,
symbols: &mut SymbolTable,
args: &[Expr],
) -> Result<()> {
compile_body(ctx, emit, &mut local, body)