Lines
54.55 %
Functions
15 %
Branches
100 %
//! `COMPILE` and `EVAL` reflective forms.
//!
//! `COMPILE` resolves a quoted symbol to its function definition and
//! returns a quoted symbol marking it as compiled (the marker is what
//! the next pipeline stage picks up; today the marker just round-
//! trips). `EVAL` resolves its argument and re-runs the evaluator on
//! the inner form.
use tracing::debug;
use crate::ast::{Expr, WasmType};
use crate::compiler::context::CompileContext;
use crate::compiler::emit::FunctionEmitter;
use crate::compiler::expr::{compile_expr, compile_for_stack, eval_value, resolve_arg};
use crate::error::{Error, Result};
use crate::runtime::SymbolTable;
use super::compile_static_result_for_stack;
pub(super) fn compile_compile_form(
ctx: &mut CompileContext,
emit: &mut FunctionEmitter,
symbols: &mut SymbolTable,
args: &[Expr],
) -> Result<()> {
let result = compile_form(symbols, args)?;
compile_expr(ctx, emit, symbols, &result)
}
pub(super) fn compile_eval_form(
if args.len() != 1 {
return Err(Error::Arity {
name: "eval".to_string(),
expected: 1,
actual: args.len(),
});
let resolved = resolve_arg(symbols, &args[0])?;
match &resolved {
Expr::Quote(inner) => compile_expr(ctx, emit, symbols, inner),
_ => compile_expr(ctx, emit, symbols, &resolved),
pub(super) fn compile_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
name: "compile".to_string(),
let name = match &args[0] {
Expr::Quote(inner) => match inner.as_ref() {
Expr::Symbol(s) => s,
_ => {
return Err(Error::Compile(
"compile: argument must be a quoted symbol".to_string(),
));
},
Expr::Symbol(_) => {
Expr::Symbol(s) => {
return compile_form_with_name(symbols, s);
};
compile_form_with_name(symbols, name)
pub(super) fn compile_form_with_name(symbols: &mut SymbolTable, name: &str) -> Result<Expr> {
debug!(function = %name, "compiling compile");
let sym = symbols
.lookup(name)
.ok_or_else(|| Error::UndefinedSymbol(name.to_string()))?;
if sym.function().is_none() {
return Err(Error::Compile(format!(
"compile: '{name}' is not a function"
)));
Ok(Expr::Quote(Box::new(Expr::Symbol(name.to_string()))))
pub(super) fn eval_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
let resolved = eval_value(symbols, &args[0])?;
debug!(expr = ?resolved, "compiling eval");
Expr::Quote(inner) => eval_value(symbols, inner),
_ => eval_value(symbols, &resolved),
pub(super) fn compile_compile_form_for_stack(
) -> Result<WasmType> {
compile_static_result_for_stack(ctx, emit, symbols, &result)
pub(super) fn compile_eval_form_for_stack(
Expr::Quote(inner) => compile_for_stack(ctx, emit, symbols, inner),
_ => compile_for_stack(ctx, emit, symbols, &resolved),