Skip to main content

nomiscript/compiler/special/
mod.rs

1mod binding;
2mod compile_eval;
3mod control;
4mod iteration;
5mod labels;
6mod lambda;
7mod macros;
8mod structure;
9
10use tracing::debug;
11
12use crate::ast::Expr;
13use crate::error::{Error, Result};
14use crate::runtime::SymbolTable;
15
16use crate::ast::WasmType;
17
18use super::context::CompileContext;
19use super::emit::FunctionEmitter;
20
21pub(in crate::compiler) use control::is_truthy;
22pub(in crate::compiler) use structure::set_place as setf_set_place;
23
24pub fn call(symbols: &mut SymbolTable, name: &str, args: &[Expr]) -> Result<Expr> {
25    debug!(special_form = %name, args = args.len(), "calling special form");
26    match name {
27        "QUOTE" => control::quote(args),
28        "DEFUN" => binding::defun(symbols, args),
29        "LAMBDA" => lambda::lambda(args),
30        "FUNCTION" => lambda::function_form(symbols, args),
31        "DEFVAR" => binding::defvar(symbols, args),
32        "DEFPARAMETER" => binding::defparameter(symbols, args),
33        "DESCRIBE" => compile_eval::describe(symbols, args),
34        "FUNCALL" => lambda::funcall(symbols, args),
35        "APPLY" => lambda::apply(symbols, args),
36        "BEGIN" => control::begin_form(symbols, args),
37        "AND" => control::and_form(symbols, args),
38        "OR" => control::or_form(symbols, args),
39        "IF" => control::if_form(symbols, args),
40        "COND" => control::cond_form(symbols, args),
41        "LET" => binding::let_form(symbols, args),
42        "LET*" => binding::let_star(symbols, args),
43        "DO" => iteration::do_form(symbols, args),
44        "DO*" => iteration::do_star_form(symbols, args),
45        "DEFMACRO" => macros::defmacro(symbols, args),
46        "MACROEXPAND-1" => macros::macroexpand_1(symbols, args),
47        "MACROEXPAND" => macros::macroexpand(symbols, args),
48        "COMPILE" => compile_eval::compile_form(symbols, args),
49        "EVAL" => compile_eval::eval_form(symbols, args),
50        "LABELS" => labels::labels_form(symbols, args),
51        "DOLIST" => iteration::dolist_form(symbols, args),
52        "DEFSTRUCT" => structure::defstruct(symbols, args),
53        "SETF" => structure::setf(symbols, args),
54        _ => Err(Error::Compile(format!(
55            "special form '{name}' not yet implemented"
56        ))),
57    }
58}
59
60pub(super) fn compile(
61    ctx: &mut CompileContext,
62    emit: &mut FunctionEmitter,
63    symbols: &mut SymbolTable,
64    name: &str,
65    args: &[Expr],
66) -> Result<()> {
67    debug!(special_form = %name, args = args.len(), "compiling special form");
68    match name {
69        "QUOTE" => control::compile_quote(ctx, emit, args),
70        "DEFUN" => binding::compile_defun(ctx, emit, symbols, args),
71        "LAMBDA" => lambda::compile_lambda_form(ctx, emit, args),
72        "FUNCTION" => lambda::compile_function_form(ctx, emit, symbols, args),
73        "DEFVAR" => binding::compile_defvar(ctx, emit, symbols, args),
74        "DEFPARAMETER" => binding::compile_defparam(ctx, emit, symbols, args),
75        "DESCRIBE" => compile_eval::compile_describe(ctx, emit, symbols, args),
76        "FUNCALL" => lambda::compile_funcall(ctx, emit, symbols, args),
77        "APPLY" => lambda::compile_apply_form(ctx, emit, symbols, args),
78        "BEGIN" => control::compile_begin(ctx, emit, symbols, args),
79        "AND" => control::compile_and(ctx, emit, symbols, args),
80        "OR" => control::compile_or(ctx, emit, symbols, args),
81        "IF" => control::compile_if(ctx, emit, symbols, args),
82        "COND" => control::compile_cond(ctx, emit, symbols, args),
83        "LET" => binding::compile_let(ctx, emit, symbols, args),
84        "LET*" => binding::compile_let_star(ctx, emit, symbols, args),
85        "DO" => iteration::compile_do(ctx, emit, symbols, args),
86        "DO*" => iteration::compile_do_star(ctx, emit, symbols, args),
87        "DEFMACRO" => macros::compile_defmacro_form(ctx, emit, symbols, args),
88        "MACROEXPAND-1" => macros::compile_macroexpand_1_form(ctx, emit, symbols, args),
89        "MACROEXPAND" => macros::compile_macroexpand_form(ctx, emit, symbols, args),
90        "COMPILE" => compile_eval::compile_compile_form(ctx, emit, symbols, args),
91        "EVAL" => compile_eval::compile_eval_form(ctx, emit, symbols, args),
92        "LABELS" => labels::compile_labels(ctx, emit, symbols, args),
93        "DOLIST" => iteration::compile_dolist(ctx, emit, symbols, args),
94        "DEFSTRUCT" => structure::compile_defstruct(ctx, emit, symbols, args),
95        "SETF" => structure::compile_setf(ctx, emit, symbols, args),
96        _ => Err(Error::Compile(format!(
97            "special form '{name}' not yet implemented"
98        ))),
99    }
100}
101
102pub(super) fn compile_for_effect(
103    ctx: &mut CompileContext,
104    emit: &mut FunctionEmitter,
105    symbols: &mut SymbolTable,
106    name: &str,
107    args: &[Expr],
108) -> Result<()> {
109    match name {
110        "DO" => iteration::compile_do_for_effect(ctx, emit, symbols, args),
111        "DO*" => iteration::compile_do_star_for_effect(ctx, emit, symbols, args),
112        "DOLIST" => iteration::compile_dolist_for_effect(ctx, emit, symbols, args),
113        "LET" => binding::compile_let_for_effect(ctx, emit, symbols, args),
114        "LET*" => binding::compile_let_star_for_effect(ctx, emit, symbols, args),
115        "COND" => control::compile_cond_for_effect(ctx, emit, symbols, args),
116        "AND" => control::compile_and_for_effect(ctx, emit, symbols, args),
117        "OR" => control::compile_or_for_effect(ctx, emit, symbols, args),
118        _ => compile(ctx, emit, symbols, name, args),
119    }
120}
121
122pub(super) fn compile_for_stack(
123    ctx: &mut CompileContext,
124    emit: &mut FunctionEmitter,
125    symbols: &mut SymbolTable,
126    name: &str,
127    args: &[Expr],
128) -> Result<WasmType> {
129    match name {
130        "IF" => control::compile_if_for_stack(ctx, emit, symbols, args),
131        "AND" => control::compile_and_for_stack(ctx, emit, symbols, args),
132        "OR" => control::compile_or_for_stack(ctx, emit, symbols, args),
133        "DO" => iteration::compile_do_for_stack(ctx, emit, symbols, args),
134        "DO*" => iteration::compile_do_star_for_stack(ctx, emit, symbols, args),
135        "LET" => binding::compile_let_for_stack(ctx, emit, symbols, args),
136        "LET*" => binding::compile_let_star_for_stack(ctx, emit, symbols, args),
137        "BEGIN" => control::compile_begin_for_stack(ctx, emit, symbols, args),
138        _ => Err(Error::Compile(format!(
139            "special form '{name}' cannot produce stack value"
140        ))),
141    }
142}