1
use tracing::debug;
2

            
3
use crate::ast::{Expr, LambdaParams};
4
use crate::error::{Error, Result};
5
use crate::runtime::{Symbol, SymbolKind, SymbolTable};
6

            
7
use super::context::CompileContext;
8
use super::emit::FunctionEmitter;
9
use super::expr::{
10
    compile_body, compile_call, compile_expr, compile_for_effect, compile_nil, compile_quoted_expr,
11
    compile_string, eval_value, format_expr, resolve_arg,
12
};
13

            
14
54007
pub fn call(symbols: &mut SymbolTable, name: &str, args: &[Expr]) -> Result<Expr> {
15
54007
    debug!(special_form = %name, args = args.len(), "calling special form");
16
54007
    match name {
17
54007
        "QUOTE" => quote(args),
18
53905
        "DEFUN" => defun(symbols, args),
19
52205
        "LAMBDA" => lambda(args),
20
51899
        "FUNCTION" => function_form(symbols, args),
21
51865
        "DEFVAR" => defvar(symbols, args),
22
51661
        "DEFPARAMETER" => defparameter(symbols, args),
23
51593
        "DESCRIBE" => describe(symbols, args),
24
51593
        "FUNCALL" => funcall(symbols, args),
25
51593
        "APPLY" => apply(symbols, args),
26
51423
        "BEGIN" => begin_form(symbols, args),
27
51355
        "AND" => and_form(symbols, args),
28
51083
        "OR" => or_form(symbols, args),
29
51083
        "IF" => if_form(symbols, args),
30
50267
        "COND" => cond_form(symbols, args),
31
50267
        "LET" => let_form(symbols, args),
32
50267
        "LET*" => let_star(symbols, args),
33
50267
        "DO" => do_form(symbols, args),
34
50267
        "DO*" => do_star_form(symbols, args),
35
50267
        "DEFMACRO" => defmacro(symbols, args),
36
44045
        "MACROEXPAND-1" => macroexpand_1(symbols, args),
37
44011
        "MACROEXPAND" => macroexpand(symbols, args),
38
44011
        "COMPILE" => compile_form(symbols, args),
39
44011
        "EVAL" => eval_form(symbols, args),
40
43943
        "LABELS" => labels_form(symbols, args),
41
43943
        "DOLIST" => dolist_form(symbols, args),
42
43637
        "DEFSTRUCT" => defstruct(symbols, args),
43
68
        "SETF" => setf(symbols, args),
44
        _ => Err(Error::Compile(format!(
45
            "special form '{name}' not yet implemented"
46
        ))),
47
    }
48
54007
}
49

            
50
// WASM compile dispatch
51

            
52
8978
pub(super) fn compile(
53
8978
    ctx: &mut CompileContext,
54
8978
    emit: &mut FunctionEmitter,
55
8978
    symbols: &mut SymbolTable,
56
8978
    name: &str,
57
8978
    args: &[Expr],
58
8978
) -> Result<()> {
59
8978
    debug!(special_form = %name, args = args.len(), "compiling special form");
60
8978
    match name {
61
8978
        "QUOTE" => compile_quote(ctx, emit, args),
62
8910
        "DEFUN" => compile_defun(ctx, emit, symbols, args),
63
8840
        "LAMBDA" => compile_lambda_form(ctx, emit, args),
64
8806
        "FUNCTION" => compile_function_form(ctx, emit, symbols, args),
65
8806
        "DEFVAR" => compile_defvar(ctx, emit, symbols, args),
66
8806
        "DEFPARAMETER" => compile_defparam(ctx, emit, symbols, args),
67
8806
        "DESCRIBE" => compile_describe(ctx, emit, symbols, args),
68
8704
        "FUNCALL" => compile_funcall(ctx, emit, symbols, args),
69
8534
        "APPLY" => compile_apply_form(ctx, emit, symbols, args),
70
8466
        "BEGIN" => compile_begin(ctx, emit, symbols, args),
71
8432
        "AND" => compile_and(ctx, emit, symbols, args),
72
8432
        "OR" => compile_or(ctx, emit, symbols, args),
73
8432
        "IF" => compile_if(ctx, emit, symbols, args),
74
7412
        "COND" => compile_cond(ctx, emit, symbols, args),
75
7140
        "LET" => compile_let(ctx, emit, symbols, args),
76
6698
        "LET*" => compile_let_star(ctx, emit, symbols, args),
77
6528
        "DO" => compile_do(ctx, emit, symbols, args),
78
6290
        "DO*" => compile_do_star(ctx, emit, symbols, args),
79
6222
        "DEFMACRO" => compile_defmacro_form(ctx, emit, symbols, args),
80
476
        "MACROEXPAND-1" => compile_macroexpand_1_form(ctx, emit, symbols, args),
81
408
        "MACROEXPAND" => compile_macroexpand_form(ctx, emit, symbols, args),
82
374
        "COMPILE" => compile_compile_form(ctx, emit, symbols, args),
83
340
        "EVAL" => compile_eval_form(ctx, emit, symbols, args),
84
170
        "LABELS" => compile_labels(ctx, emit, symbols, args),
85
        "DOLIST" => compile_dolist(ctx, emit, symbols, args),
86
        "DEFSTRUCT" => compile_defstruct(ctx, emit, symbols, args),
87
        "SETF" => compile_setf(ctx, emit, symbols, args),
88
        _ => Err(Error::Compile(format!(
89
            "special form '{name}' not yet implemented"
90
        ))),
91
    }
92
8978
}
93

            
94
68
fn compile_quote(
95
68
    ctx: &mut CompileContext,
96
68
    emit: &mut FunctionEmitter,
97
68
    args: &[Expr],
98
68
) -> Result<()> {
99
68
    if args.len() != 1 {
100
        return Err(Error::Arity {
101
            name: "quote".to_string(),
102
            expected: 1,
103
            actual: args.len(),
104
        });
105
68
    }
106
68
    compile_quoted_expr(ctx, emit, &args[0])
107
68
}
108

            
109
70
fn compile_defun(
110
70
    ctx: &mut CompileContext,
111
70
    emit: &mut FunctionEmitter,
112
70
    symbols: &mut SymbolTable,
113
70
    args: &[Expr],
114
70
) -> Result<()> {
115
70
    let result = defun(symbols, args)?;
116
70
    compile_expr(ctx, emit, symbols, &result)
117
70
}
118

            
119
34
fn compile_lambda_form(
120
34
    ctx: &mut CompileContext,
121
34
    emit: &mut FunctionEmitter,
122
34
    args: &[Expr],
123
34
) -> Result<()> {
124
34
    let result = lambda(args)?;
125
34
    compile_string(ctx, emit, &format_expr(&result));
126
34
    Ok(())
127
34
}
128

            
129
fn compile_function_form(
130
    ctx: &mut CompileContext,
131
    emit: &mut FunctionEmitter,
132
    symbols: &mut SymbolTable,
133
    args: &[Expr],
134
) -> Result<()> {
135
    let result = function_form(symbols, args)?;
136
    compile_string(ctx, emit, &format_expr(&result));
137
    Ok(())
138
}
139

            
140
fn compile_defvar(
141
    ctx: &mut CompileContext,
142
    emit: &mut FunctionEmitter,
143
    symbols: &mut SymbolTable,
144
    args: &[Expr],
145
) -> Result<()> {
146
    let result = defvar(symbols, args)?;
147
    compile_expr(ctx, emit, symbols, &result)
148
}
149

            
150
fn compile_defparam(
151
    ctx: &mut CompileContext,
152
    emit: &mut FunctionEmitter,
153
    symbols: &mut SymbolTable,
154
    args: &[Expr],
155
) -> Result<()> {
156
    let result = defparameter(symbols, args)?;
157
    compile_expr(ctx, emit, symbols, &result)
158
}
159

            
160
102
fn compile_describe(
161
102
    ctx: &mut CompileContext,
162
102
    emit: &mut FunctionEmitter,
163
102
    symbols: &mut SymbolTable,
164
102
    args: &[Expr],
165
102
) -> Result<()> {
166
102
    let result = describe(symbols, args)?;
167
102
    compile_expr(ctx, emit, symbols, &result)
168
102
}
169

            
170
170
fn compile_funcall(
171
170
    ctx: &mut CompileContext,
172
170
    emit: &mut FunctionEmitter,
173
170
    symbols: &mut SymbolTable,
174
170
    args: &[Expr],
175
170
) -> Result<()> {
176
170
    if args.is_empty() {
177
        return Err(Error::Compile(
178
            "funcall requires at least a function argument".to_string(),
179
        ));
180
170
    }
181
170
    compile_call(ctx, emit, symbols, args)
182
170
}
183

            
184
68
fn compile_apply_form(
185
68
    ctx: &mut CompileContext,
186
68
    emit: &mut FunctionEmitter,
187
68
    symbols: &mut SymbolTable,
188
68
    args: &[Expr],
189
68
) -> Result<()> {
190
68
    if args.len() < 2 {
191
        return Err(Error::Compile(
192
            "apply requires at least a function and one argument".to_string(),
193
        ));
194
68
    }
195
68
    let leading = &args[..args.len() - 1];
196
68
    let last = eval_value(symbols, &args[args.len() - 1])?;
197

            
198
68
    let spread = match &last {
199
68
        Expr::Quote(inner) => match inner.as_ref() {
200
68
            Expr::List(elems) => elems.clone(),
201
            Expr::Nil => vec![],
202
            _ => {
203
                return Err(Error::Compile(
204
                    "apply: last argument must be a quoted list".to_string(),
205
                ));
206
            }
207
        },
208
        _ => {
209
            return Err(Error::Compile(
210
                "apply: last argument must be a quoted list".to_string(),
211
            ));
212
        }
213
    };
214

            
215
68
    let mut all_args: Vec<Expr> = Vec::with_capacity(leading.len() + spread.len());
216
68
    all_args.push(resolve_apply_designator(symbols, &leading[0])?);
217
68
    for arg in &leading[1..] {
218
68
        all_args.push(eval_value(symbols, arg)?);
219
    }
220
68
    all_args.extend(spread);
221
68
    compile_call(ctx, emit, symbols, &all_args)
222
68
}
223

            
224
1020
fn compile_if(
225
1020
    ctx: &mut CompileContext,
226
1020
    emit: &mut FunctionEmitter,
227
1020
    symbols: &mut SymbolTable,
228
1020
    args: &[Expr],
229
1020
) -> Result<()> {
230
1020
    if args.len() < 2 || args.len() > 3 {
231
68
        return Err(Error::Compile(
232
68
            "IF requires a test, a then-form, and an optional else-form".to_string(),
233
68
        ));
234
952
    }
235
952
    let test = eval_value(symbols, &args[0])?;
236
952
    if is_truthy(&test) {
237
442
        compile_expr(ctx, emit, symbols, &args[1])
238
510
    } else if args.len() == 3 {
239
442
        compile_expr(ctx, emit, symbols, &args[2])
240
    } else {
241
68
        compile_nil(emit);
242
68
        Ok(())
243
    }
244
1020
}
245

            
246
34
fn compile_begin(
247
34
    ctx: &mut CompileContext,
248
34
    emit: &mut FunctionEmitter,
249
34
    symbols: &mut SymbolTable,
250
34
    args: &[Expr],
251
34
) -> Result<()> {
252
34
    if args.is_empty() {
253
        compile_nil(emit);
254
        return Ok(());
255
34
    }
256
34
    compile_body(ctx, emit, symbols, args)
257
34
}
258

            
259
fn compile_and(
260
    ctx: &mut CompileContext,
261
    emit: &mut FunctionEmitter,
262
    symbols: &mut SymbolTable,
263
    args: &[Expr],
264
) -> Result<()> {
265
    if args.is_empty() {
266
        return compile_expr(ctx, emit, symbols, &Expr::Bool(true));
267
    }
268

            
269
    let mut last = Expr::Bool(true);
270
    for arg in args {
271
        let value = eval_value(symbols, arg)?;
272
        if !is_truthy(&value) {
273
            return compile_expr(ctx, emit, symbols, &value);
274
        }
275
        last = value;
276
    }
277
    compile_expr(ctx, emit, symbols, &last)
278
}
279

            
280
fn compile_or(
281
    ctx: &mut CompileContext,
282
    emit: &mut FunctionEmitter,
283
    symbols: &mut SymbolTable,
284
    args: &[Expr],
285
) -> Result<()> {
286
    if args.is_empty() {
287
        compile_nil(emit);
288
        return Ok(());
289
    }
290

            
291
    let mut last = Expr::Nil;
292
    for arg in args {
293
        let value = eval_value(symbols, arg)?;
294
        if is_truthy(&value) {
295
            return compile_expr(ctx, emit, symbols, &value);
296
        }
297
        last = value;
298
    }
299
    compile_expr(ctx, emit, symbols, &last)
300
}
301

            
302
272
fn compile_cond(
303
272
    ctx: &mut CompileContext,
304
272
    emit: &mut FunctionEmitter,
305
272
    symbols: &mut SymbolTable,
306
272
    args: &[Expr],
307
272
) -> Result<()> {
308
340
    for clause in args {
309
340
        let elems = clause.as_list().ok_or_else(|| {
310
            Error::Compile(format!("COND: clause must be a list, got {clause:?}"))
311
        })?;
312
340
        if elems.is_empty() {
313
            return Err(Error::Compile("COND: empty clause".to_string()));
314
340
        }
315
340
        let test = eval_value(symbols, &elems[0])?;
316
340
        if is_truthy(&test) {
317
204
            if elems.len() == 1 {
318
34
                return compile_expr(ctx, emit, symbols, &test);
319
170
            }
320
170
            return compile_body(ctx, emit, symbols, &elems[1..]);
321
136
        }
322
    }
323
68
    compile_nil(emit);
324
68
    Ok(())
325
272
}
326

            
327
442
fn compile_let(
328
442
    ctx: &mut CompileContext,
329
442
    emit: &mut FunctionEmitter,
330
442
    symbols: &mut SymbolTable,
331
442
    args: &[Expr],
332
442
) -> Result<()> {
333
442
    if args.len() < 2 {
334
34
        return Err(Error::Compile(
335
34
            "LET requires a bindings list and at least one body form".to_string(),
336
34
        ));
337
408
    }
338
408
    let bindings = parse_bindings("LET", &args[0])?;
339
374
    let resolved: Vec<(String, Expr)> = bindings
340
374
        .into_iter()
341
544
        .map(|(name, init)| {
342
544
            let val = match init {
343
510
                Some(expr) => eval_value(symbols, &expr)?,
344
34
                None => Expr::Nil,
345
            };
346
544
            Ok((name, val))
347
544
        })
348
374
        .collect::<Result<_>>()?;
349
374
    let mut local = symbols.clone();
350
544
    for (name, val) in resolved {
351
544
        local.define(Symbol::new(&name, SymbolKind::Variable).with_value(val));
352
544
    }
353
374
    compile_body(ctx, emit, &mut local, &args[1..])
354
442
}
355

            
356
170
fn compile_let_star(
357
170
    ctx: &mut CompileContext,
358
170
    emit: &mut FunctionEmitter,
359
170
    symbols: &mut SymbolTable,
360
170
    args: &[Expr],
361
170
) -> Result<()> {
362
170
    if args.len() < 2 {
363
34
        return Err(Error::Compile(
364
34
            "LET* requires a bindings list and at least one body form".to_string(),
365
34
        ));
366
136
    }
367
136
    let bindings = parse_bindings("LET*", &args[0])?;
368
136
    let mut local = symbols.clone();
369
306
    for (name, init) in bindings {
370
306
        let val = match init {
371
306
            Some(expr) => eval_value(&mut local, &expr)?,
372
            None => Expr::Nil,
373
        };
374
306
        local.define(Symbol::new(&name, SymbolKind::Variable).with_value(val));
375
    }
376
136
    compile_body(ctx, emit, &mut local, &args[1..])
377
170
}
378

            
379
238
fn compile_do(
380
238
    ctx: &mut CompileContext,
381
238
    emit: &mut FunctionEmitter,
382
238
    symbols: &mut SymbolTable,
383
238
    args: &[Expr],
384
238
) -> Result<()> {
385
238
    if args.len() < 2 {
386
68
        return Err(Error::Compile(
387
68
            "DO requires a variable list and an end clause".to_string(),
388
68
        ));
389
170
    }
390
170
    let vars = parse_do_vars("DO", &args[0])?;
391
170
    let (end_test, result_forms) = parse_end_clause("DO", &args[1])?;
392
170
    let end_test = end_test.clone();
393
170
    let result_forms: Vec<Expr> = result_forms.to_vec();
394
170
    let body = &args[2..];
395

            
396
170
    let init_values: Vec<(String, Expr, Option<Expr>)> = vars
397
170
        .into_iter()
398
238
        .map(|v| {
399
238
            let val = match v.init {
400
204
                Some(expr) => eval_value(symbols, &expr)?,
401
34
                None => Expr::Nil,
402
            };
403
238
            Ok((v.name, val, v.step))
404
238
        })
405
170
        .collect::<Result<_>>()?;
406

            
407
170
    let mut local = symbols.clone();
408
170
    let mut stepped: Vec<(String, Option<Expr>)> = Vec::new();
409
238
    for (name, val, step) in &init_values {
410
238
        local.define(Symbol::new(name, SymbolKind::Variable).with_value(val.clone()));
411
238
        stepped.push((name.clone(), step.clone()));
412
238
    }
413

            
414
    loop {
415
714
        let test = eval_value(&mut local, &end_test)?;
416
714
        if is_truthy(&test) {
417
170
            return if result_forms.is_empty() {
418
34
                compile_nil(emit);
419
34
                Ok(())
420
            } else {
421
136
                compile_body(ctx, emit, &mut local, &result_forms)
422
            };
423
544
        }
424
544
        for expr in body {
425
            compile_for_effect(ctx, emit, &mut local, expr)?;
426
        }
427
544
        let new_values: Vec<(&str, Expr)> = stepped
428
544
            .iter()
429
816
            .filter_map(|(name, step)| {
430
816
                step.as_ref()
431
816
                    .map(|s| eval_value(&mut local, s).map(|v| (name.as_str(), v)))
432
816
            })
433
544
            .collect::<Result<_>>()?;
434
714
        for (name, val) in new_values {
435
714
            local
436
714
                .lookup_mut(name)
437
714
                .expect("DO variable must exist")
438
714
                .set_value(val);
439
714
        }
440
    }
441
238
}
442

            
443
68
fn compile_do_star(
444
68
    ctx: &mut CompileContext,
445
68
    emit: &mut FunctionEmitter,
446
68
    symbols: &mut SymbolTable,
447
68
    args: &[Expr],
448
68
) -> Result<()> {
449
68
    if args.len() < 2 {
450
        return Err(Error::Compile(
451
            "DO* requires a variable list and an end clause".to_string(),
452
        ));
453
68
    }
454
68
    let vars = parse_do_vars("DO*", &args[0])?;
455
68
    let (end_test, result_forms) = parse_end_clause("DO*", &args[1])?;
456
68
    let end_test = end_test.clone();
457
68
    let result_forms: Vec<Expr> = result_forms.to_vec();
458
68
    let body = &args[2..];
459

            
460
68
    let mut local = symbols.clone();
461
68
    let mut stepped: Vec<(String, Option<Expr>)> = Vec::new();
462
136
    for v in vars {
463
136
        let val = match v.init {
464
136
            Some(expr) => eval_value(&mut local, &expr)?,
465
            None => Expr::Nil,
466
        };
467
136
        local.define(Symbol::new(&v.name, SymbolKind::Variable).with_value(val));
468
136
        stepped.push((v.name, v.step));
469
    }
470

            
471
    loop {
472
170
        let test = eval_value(&mut local, &end_test)?;
473
170
        if is_truthy(&test) {
474
68
            return if result_forms.is_empty() {
475
                compile_nil(emit);
476
                Ok(())
477
            } else {
478
68
                compile_body(ctx, emit, &mut local, &result_forms)
479
            };
480
102
        }
481
102
        for expr in body {
482
            compile_for_effect(ctx, emit, &mut local, expr)?;
483
        }
484
204
        for (name, step) in &stepped {
485
204
            if let Some(s) = step {
486
204
                let val = eval_value(&mut local, s)?;
487
204
                local
488
204
                    .lookup_mut(name)
489
204
                    .expect("DO* variable must exist")
490
204
                    .set_value(val);
491
            }
492
        }
493
    }
494
68
}
495

            
496
5746
fn compile_defmacro_form(
497
5746
    ctx: &mut CompileContext,
498
5746
    emit: &mut FunctionEmitter,
499
5746
    symbols: &mut SymbolTable,
500
5746
    args: &[Expr],
501
5746
) -> Result<()> {
502
5746
    let result = defmacro(symbols, args)?;
503
5746
    compile_expr(ctx, emit, symbols, &result)
504
5746
}
505

            
506
68
fn compile_macroexpand_1_form(
507
68
    ctx: &mut CompileContext,
508
68
    emit: &mut FunctionEmitter,
509
68
    symbols: &mut SymbolTable,
510
68
    args: &[Expr],
511
68
) -> Result<()> {
512
68
    let result = macroexpand_1(symbols, args)?;
513
68
    compile_expr(ctx, emit, symbols, &result)
514
68
}
515

            
516
34
fn compile_macroexpand_form(
517
34
    ctx: &mut CompileContext,
518
34
    emit: &mut FunctionEmitter,
519
34
    symbols: &mut SymbolTable,
520
34
    args: &[Expr],
521
34
) -> Result<()> {
522
34
    let result = macroexpand(symbols, args)?;
523
34
    compile_expr(ctx, emit, symbols, &result)
524
34
}
525

            
526
34
fn compile_compile_form(
527
34
    ctx: &mut CompileContext,
528
34
    emit: &mut FunctionEmitter,
529
34
    symbols: &mut SymbolTable,
530
34
    args: &[Expr],
531
34
) -> Result<()> {
532
34
    let result = compile_form(symbols, args)?;
533
34
    compile_expr(ctx, emit, symbols, &result)
534
34
}
535

            
536
170
fn compile_eval_form(
537
170
    ctx: &mut CompileContext,
538
170
    emit: &mut FunctionEmitter,
539
170
    symbols: &mut SymbolTable,
540
170
    args: &[Expr],
541
170
) -> Result<()> {
542
170
    if args.len() != 1 {
543
        return Err(Error::Arity {
544
            name: "eval".to_string(),
545
            expected: 1,
546
            actual: args.len(),
547
        });
548
170
    }
549
170
    let resolved = resolve_arg(symbols, &args[0])?;
550
170
    match &resolved {
551
68
        Expr::Quote(inner) => compile_expr(ctx, emit, symbols, inner),
552
102
        _ => compile_expr(ctx, emit, symbols, &resolved),
553
    }
554
170
}
555

            
556
// Eval dispatch
557

            
558
102
fn quote(args: &[Expr]) -> Result<Expr> {
559
102
    if args.len() != 1 {
560
        return Err(Error::Arity {
561
            name: "quote".to_string(),
562
            expected: 1,
563
            actual: args.len(),
564
        });
565
102
    }
566
102
    Ok(args[0].clone())
567
102
}
568

            
569
340
fn lambda(args: &[Expr]) -> Result<Expr> {
570
340
    if args.len() < 2 {
571
        return Err(Error::Compile(
572
            "LAMBDA requires a parameter list and body".to_string(),
573
        ));
574
340
    }
575
340
    let params = parse_lambda_params("LAMBDA", &args[0])?;
576
340
    let body = if args.len() == 2 {
577
340
        args[1].clone()
578
    } else {
579
        let mut forms = Vec::with_capacity(args.len());
580
        forms.push(Expr::Symbol("BEGIN".to_string()));
581
        forms.extend_from_slice(&args[1..]);
582
        Expr::List(forms)
583
    };
584
340
    Ok(Expr::Lambda(params, Box::new(body)))
585
340
}
586

            
587
1770
fn defun(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
588
1770
    if args.len() < 3 {
589
        return Err(Error::Compile(
590
            "DEFUN requires a name, parameter list, and body".to_string(),
591
        ));
592
1770
    }
593
1770
    let name = match &args[0] {
594
1770
        Expr::Symbol(s) => s.clone(),
595
        other => {
596
            return Err(Error::Compile(format!(
597
                "DEFUN: expected symbol name, got {other:?}"
598
            )));
599
        }
600
    };
601
1770
    let params = parse_lambda_params("DEFUN", &args[1])?;
602
1770
    let (doc, body_idx) = match args.get(2) {
603
69
        Some(Expr::String(s)) if args.len() > 3 => (Some(s.clone()), 3),
604
1701
        _ => (None, 2),
605
    };
606
1770
    if body_idx >= args.len() {
607
        return Err(Error::Compile("DEFUN: missing body".to_string()));
608
1770
    }
609
1770
    let body = if args.len() == body_idx + 1 {
610
1702
        args[body_idx].clone()
611
    } else {
612
68
        let mut forms = Vec::with_capacity(args.len() - body_idx + 1);
613
68
        forms.push(Expr::Symbol("BEGIN".to_string()));
614
68
        forms.extend_from_slice(&args[body_idx..]);
615
68
        Expr::List(forms)
616
    };
617
1770
    let lambda = Expr::Lambda(params, Box::new(body));
618

            
619
1770
    if let Some(sym) = symbols.lookup_mut(&name) {
620
        sym.set_function(lambda);
621
        if let Some(d) = doc {
622
            sym.set_doc(d);
623
        }
624
    } else {
625
1770
        let mut sym = Symbol::new(&name, SymbolKind::Variable).with_function(lambda);
626
1770
        if let Some(d) = doc {
627
69
            sym = sym.with_doc(d);
628
1701
        }
629
1770
        symbols.define(sym);
630
    }
631
1770
    Ok(Expr::Quote(Box::new(Expr::Symbol(name))))
632
1770
}
633

            
634
34
fn function_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
635
34
    if args.len() != 1 {
636
        return Err(Error::Arity {
637
            name: "FUNCTION".to_string(),
638
            expected: 1,
639
            actual: args.len(),
640
        });
641
34
    }
642
34
    match &args[0] {
643
34
        Expr::Symbol(name) => {
644
34
            let func = symbols
645
34
                .lookup(name)
646
34
                .and_then(|s| s.function().cloned())
647
34
                .ok_or_else(|| Error::Compile(format!("'{name}' has no function definition")))?;
648
34
            Ok(func)
649
        }
650
        Expr::List(elems) if matches!(elems.first(), Some(Expr::Symbol(s)) if s == "LAMBDA") => {
651
            lambda(&elems[1..])
652
        }
653
        _ => Err(Error::Compile(
654
            "FUNCTION: argument must be a symbol or lambda expression".to_string(),
655
        )),
656
    }
657
34
}
658

            
659
204
fn defvar(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
660
204
    if args.is_empty() {
661
        return Err(Error::Compile(
662
            "DEFVAR requires at least a name".to_string(),
663
        ));
664
204
    }
665
204
    let name = match &args[0] {
666
204
        Expr::Symbol(s) => s.clone(),
667
        other => {
668
            return Err(Error::Compile(format!(
669
                "DEFVAR: expected symbol name, got {other:?}"
670
            )));
671
        }
672
    };
673
204
    let initial = args.get(1).map(|e| eval_value(symbols, e)).transpose()?;
674
204
    let doc = match args.get(2) {
675
34
        Some(Expr::String(s)) => Some(s.clone()),
676
170
        _ => None,
677
    };
678

            
679
204
    if let Some(sym) = symbols.lookup_mut(&name) {
680
34
        if sym.value().is_none()
681
            && let Some(val) = initial
682
        {
683
            sym.set_value(val);
684
34
        }
685
34
        if let Some(d) = doc {
686
            sym.set_doc(d);
687
34
        }
688
    } else {
689
170
        let mut sym = Symbol::new(&name, SymbolKind::Variable);
690
170
        if let Some(val) = initial {
691
170
            sym = sym.with_value(val);
692
170
        }
693
170
        if let Some(d) = doc {
694
34
            sym = sym.with_doc(d);
695
136
        }
696
170
        symbols.define(sym);
697
    }
698
204
    Ok(Expr::Quote(Box::new(Expr::Symbol(name))))
699
204
}
700

            
701
68
fn defparameter(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
702
68
    if args.len() < 2 {
703
        return Err(Error::Compile(
704
            "DEFPARAMETER requires a name and initial value".to_string(),
705
        ));
706
68
    }
707
68
    let name = match &args[0] {
708
68
        Expr::Symbol(s) => s.clone(),
709
        other => {
710
            return Err(Error::Compile(format!(
711
                "DEFPARAMETER: expected symbol name, got {other:?}"
712
            )));
713
        }
714
    };
715
68
    let value = eval_value(symbols, &args[1])?;
716
68
    let doc = match args.get(2) {
717
        Some(Expr::String(s)) => Some(s.clone()),
718
68
        _ => None,
719
    };
720

            
721
68
    if let Some(sym) = symbols.lookup_mut(&name) {
722
34
        sym.set_value(value);
723
34
        if let Some(d) = doc {
724
            sym.set_doc(d);
725
34
        }
726
    } else {
727
34
        let mut sym = Symbol::new(&name, SymbolKind::Variable).with_value(value);
728
34
        if let Some(d) = doc {
729
            sym = sym.with_doc(d);
730
34
        }
731
34
        symbols.define(sym);
732
    }
733
68
    Ok(Expr::Quote(Box::new(Expr::Symbol(name))))
734
68
}
735

            
736
102
fn describe(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
737
102
    if args.len() != 1 {
738
        return Err(Error::Arity {
739
            name: "DESCRIBE".to_string(),
740
            expected: 1,
741
            actual: args.len(),
742
        });
743
102
    }
744
102
    let name = match &args[0] {
745
102
        Expr::Symbol(s) => s.clone(),
746
        Expr::Quote(inner) => match inner.as_ref() {
747
            Expr::Symbol(s) => s.clone(),
748
            _ => {
749
                return Err(Error::Compile(
750
                    "DESCRIBE: argument must be a symbol".to_string(),
751
                ));
752
            }
753
        },
754
        _ => {
755
            return Err(Error::Compile(
756
                "DESCRIBE: argument must be a symbol".to_string(),
757
            ));
758
        }
759
    };
760
102
    let sym = symbols
761
102
        .lookup(&name)
762
102
        .ok_or_else(|| Error::UndefinedSymbol(name.clone()))?;
763

            
764
102
    let mut lines = Vec::new();
765
102
    let kind_str = match sym.kind() {
766
34
        SymbolKind::Macro => "a macro",
767
68
        _ if sym.function().is_some() => "a function",
768
34
        SymbolKind::Variable => "a variable",
769
        SymbolKind::Operator => "an operator",
770
        SymbolKind::Native => "a native function",
771
        SymbolKind::SpecialForm => "a special form",
772
        SymbolKind::Function => "a function",
773
    };
774
102
    lines.push(format!("{name} is {kind_str}"));
775
102
    if let Some(func) = sym.function() {
776
68
        lines.push(format!("  Lambda: {}", format_expr(func)));
777
68
    }
778
102
    if let Some(val) = sym.value() {
779
34
        let type_name = match val {
780
            Expr::Nil | Expr::Bool(false) => "Nil",
781
            Expr::Bool(true) => "Bool",
782
34
            Expr::Number(_) => "Number",
783
            Expr::String(_) => "String",
784
            Expr::Symbol(_) => "Symbol",
785
            Expr::Lambda(_, _) => "Lambda",
786
            _ => "Compound",
787
        };
788
34
        lines.push(format!("  Value: {} ({})", format_expr(val), type_name));
789
68
    }
790
102
    if let Some(doc) = sym.doc() {
791
68
        lines.push(format!("  Documentation: \"{doc}\""));
792
68
    }
793
102
    Ok(Expr::String(lines.join("\n")))
794
102
}
795

            
796
fn funcall(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
797
    if args.is_empty() {
798
        return Err(Error::Compile(
799
            "funcall requires at least a function argument".to_string(),
800
        ));
801
    }
802
    debug!(args = args.len(), "compiling funcall");
803
    super::expr::call(symbols, args)
804
}
805

            
806
170
fn apply(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
807
170
    if args.len() < 2 {
808
        return Err(Error::Compile(
809
            "apply requires at least a function and one argument".to_string(),
810
        ));
811
170
    }
812
170
    let leading = &args[..args.len() - 1];
813
170
    let last = eval_value(symbols, &args[args.len() - 1])?;
814

            
815
170
    let spread = match &last {
816
170
        Expr::Quote(inner) => match inner.as_ref() {
817
170
            Expr::List(elems) => elems.clone(),
818
            Expr::Nil => vec![],
819
            _ => {
820
                return Err(Error::Compile(
821
                    "apply: last argument must be a quoted list".to_string(),
822
                ));
823
            }
824
        },
825
        _ => {
826
            return Err(Error::Compile(
827
                "apply: last argument must be a quoted list".to_string(),
828
            ));
829
        }
830
    };
831

            
832
170
    let mut all_args: Vec<Expr> = Vec::with_capacity(leading.len() + spread.len());
833
170
    all_args.push(resolve_apply_designator(symbols, &leading[0])?);
834
510
    for arg in &leading[1..] {
835
510
        all_args.push(eval_value(symbols, arg)?);
836
    }
837
170
    all_args.extend(spread);
838
170
    super::expr::call(symbols, &all_args)
839
170
}
840

            
841
238
fn resolve_apply_designator(symbols: &mut SymbolTable, arg: &Expr) -> Result<Expr> {
842
238
    match arg {
843
68
        Expr::Symbol(name) => {
844
68
            let sym = symbols
845
68
                .lookup(name)
846
68
                .ok_or_else(|| Error::UndefinedSymbol(name.clone()))?;
847
68
            if sym.value().is_some() {
848
                eval_value(symbols, arg)
849
            } else {
850
68
                Ok(Expr::Symbol(name.clone()))
851
            }
852
        }
853
170
        _ => eval_value(symbols, arg),
854
    }
855
238
}
856

            
857
34
fn compile_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
858
34
    if args.len() != 1 {
859
        return Err(Error::Arity {
860
            name: "compile".to_string(),
861
            expected: 1,
862
            actual: args.len(),
863
        });
864
34
    }
865
34
    let name = match &args[0] {
866
34
        Expr::Quote(inner) => match inner.as_ref() {
867
34
            Expr::Symbol(s) => s,
868
            _ => {
869
                return Err(Error::Compile(
870
                    "compile: argument must be a quoted symbol".to_string(),
871
                ));
872
            }
873
        },
874
        Expr::Symbol(_) => {
875
            let resolved = resolve_arg(symbols, &args[0])?;
876
            match &resolved {
877
                Expr::Quote(inner) => match inner.as_ref() {
878
                    Expr::Symbol(s) => {
879
                        return compile_form_with_name(symbols, s);
880
                    }
881
                    _ => {
882
                        return Err(Error::Compile(
883
                            "compile: argument must be a quoted symbol".to_string(),
884
                        ));
885
                    }
886
                },
887
                _ => {
888
                    return Err(Error::Compile(
889
                        "compile: argument must be a quoted symbol".to_string(),
890
                    ));
891
                }
892
            }
893
        }
894
        _ => {
895
            return Err(Error::Compile(
896
                "compile: argument must be a quoted symbol".to_string(),
897
            ));
898
        }
899
    };
900
34
    compile_form_with_name(symbols, name)
901
34
}
902

            
903
34
fn compile_form_with_name(symbols: &mut SymbolTable, name: &str) -> Result<Expr> {
904
34
    debug!(function = %name, "compiling compile");
905
34
    let sym = symbols
906
34
        .lookup(name)
907
34
        .ok_or_else(|| Error::UndefinedSymbol(name.to_string()))?;
908
34
    if sym.function().is_none() {
909
        return Err(Error::Compile(format!(
910
            "compile: '{name}' is not a function"
911
        )));
912
34
    }
913
34
    Ok(Expr::Quote(Box::new(Expr::Symbol(name.to_string()))))
914
34
}
915

            
916
68
fn eval_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
917
68
    if args.len() != 1 {
918
        return Err(Error::Arity {
919
            name: "eval".to_string(),
920
            expected: 1,
921
            actual: args.len(),
922
        });
923
68
    }
924
68
    let resolved = eval_value(symbols, &args[0])?;
925
68
    debug!(expr = ?resolved, "compiling eval");
926
68
    match &resolved {
927
68
        Expr::Quote(inner) => eval_value(symbols, inner),
928
        _ => eval_value(symbols, &resolved),
929
    }
930
68
}
931

            
932
3570
fn is_truthy(expr: &Expr) -> bool {
933
3570
    !matches!(expr, Expr::Nil | Expr::Bool(false))
934
3570
}
935

            
936
816
fn if_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
937
816
    if args.len() < 2 || args.len() > 3 {
938
        return Err(Error::Compile(
939
            "IF requires a test, a then-form, and an optional else-form".to_string(),
940
        ));
941
816
    }
942
816
    let test = eval_value(symbols, &args[0])?;
943
816
    if is_truthy(&test) {
944
578
        eval_value(symbols, &args[1])
945
238
    } else if args.len() == 3 {
946
238
        eval_value(symbols, &args[2])
947
    } else {
948
        Ok(Expr::Nil)
949
    }
950
816
}
951

            
952
68
fn begin_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
953
68
    if args.is_empty() {
954
        return Ok(Expr::Nil);
955
68
    }
956
68
    eval_body(symbols, args)
957
68
}
958

            
959
272
fn and_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
960
272
    if args.is_empty() {
961
        return Ok(Expr::Bool(true));
962
272
    }
963

            
964
272
    let mut last = Expr::Bool(true);
965
578
    for arg in args {
966
578
        let value = eval_value(symbols, arg)?;
967
578
        if !is_truthy(&value) {
968
238
            return Ok(value);
969
340
        }
970
340
        last = value;
971
    }
972
34
    Ok(last)
973
272
}
974

            
975
fn or_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
976
    if args.is_empty() {
977
        return Ok(Expr::Nil);
978
    }
979

            
980
    let mut last = Expr::Nil;
981
    for arg in args {
982
        let value = eval_value(symbols, arg)?;
983
        if is_truthy(&value) {
984
            return Ok(value);
985
        }
986
        last = value;
987
    }
988
    Ok(last)
989
}
990

            
991
fn cond_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
992
    for clause in args {
993
        let elems = clause.as_list().ok_or_else(|| {
994
            Error::Compile(format!("COND: clause must be a list, got {clause:?}"))
995
        })?;
996
        if elems.is_empty() {
997
            return Err(Error::Compile("COND: empty clause".to_string()));
998
        }
999
        let test = eval_value(symbols, &elems[0])?;
        if is_truthy(&test) {
            if elems.len() == 1 {
                return Ok(test);
            }
            return eval_body(symbols, &elems[1..]);
        }
    }
    Ok(Expr::Nil)
}
68
fn eval_body(symbols: &mut SymbolTable, body: &[Expr]) -> Result<Expr> {
136
    for expr in &body[..body.len() - 1] {
136
        eval_value(symbols, expr)?;
    }
68
    eval_value(symbols, body.last().unwrap())
68
}
fn let_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
    if args.len() < 2 {
        return Err(Error::Compile(
            "LET requires a bindings list and at least one body form".to_string(),
        ));
    }
    let bindings = parse_bindings("LET", &args[0])?;
    let resolved: Vec<(String, Expr)> = bindings
        .into_iter()
        .map(|(name, init)| {
            let val = match init {
                Some(expr) => eval_value(symbols, &expr)?,
                None => Expr::Nil,
            };
            Ok((name, val))
        })
        .collect::<Result<_>>()?;
    let mut local_symbols = symbols.clone();
    for (name, val) in resolved {
        local_symbols.define(Symbol::new(&name, SymbolKind::Variable).with_value(val));
    }
    eval_body(&mut local_symbols, &args[1..])
}
fn let_star(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
    if args.len() < 2 {
        return Err(Error::Compile(
            "LET* requires a bindings list and at least one body form".to_string(),
        ));
    }
    let bindings = parse_bindings("LET*", &args[0])?;
    let mut local_symbols = symbols.clone();
    for (name, init) in bindings {
        let val = match init {
            Some(expr) => eval_value(&mut local_symbols, &expr)?,
            None => Expr::Nil,
        };
        local_symbols.define(Symbol::new(&name, SymbolKind::Variable).with_value(val));
    }
    eval_body(&mut local_symbols, &args[1..])
}
544
fn parse_bindings(context: &str, expr: &Expr) -> Result<Vec<(String, Option<Expr>)>> {
544
    let list = match expr {
544
        Expr::List(elems) => elems,
        _ => {
            return Err(Error::Compile(format!(
                "{context}: expected bindings list, got {expr:?}"
            )));
        }
    };
544
    list.iter()
850
        .map(|binding| match binding {
            Expr::Symbol(name) => Ok((name.clone(), None)),
884
            Expr::List(elems) if elems.len() == 1 => {
34
                let name = elems[0].as_symbol().ok_or_else(|| {
                    Error::Compile(format!(
                        "{context}: binding name must be a symbol, got {:?}",
                        elems[0]
                    ))
                })?;
34
                Ok((name.to_string(), None))
            }
850
            Expr::List(elems) if elems.len() == 2 => {
850
                let name = elems[0].as_symbol().ok_or_else(|| {
34
                    Error::Compile(format!(
34
                        "{context}: binding name must be a symbol, got {:?}",
34
                        elems[0]
34
                    ))
34
                })?;
816
                Ok((name.to_string(), Some(elems[1].clone())))
            }
            _ => Err(Error::Compile(format!(
                "{context}: malformed binding: {binding:?}"
            ))),
884
        })
544
        .collect()
544
}
struct DoVar {
    name: String,
    init: Option<Expr>,
    step: Option<Expr>,
}
238
fn parse_do_vars(context: &str, expr: &Expr) -> Result<Vec<DoVar>> {
238
    let list = match expr {
238
        Expr::List(elems) => elems,
        _ => {
            return Err(Error::Compile(format!(
                "{context}: expected variable list, got {expr:?}"
            )));
        }
    };
238
    list.iter()
374
        .map(|spec| match spec {
            Expr::Symbol(name) => Ok(DoVar {
                name: name.clone(),
                init: None,
                step: None,
            }),
374
            Expr::List(elems) if !elems.is_empty() && elems.len() <= 3 => {
374
                let name = elems[0].as_symbol().ok_or_else(|| {
                    Error::Compile(format!(
                        "{context}: variable name must be a symbol, got {:?}",
                        elems[0]
                    ))
                })?;
374
                Ok(DoVar {
374
                    name: name.to_string(),
374
                    init: elems.get(1).cloned(),
374
                    step: elems.get(2).cloned(),
374
                })
            }
            _ => Err(Error::Compile(format!(
                "{context}: malformed variable spec: {spec:?}"
            ))),
374
        })
238
        .collect()
238
}
238
fn parse_end_clause<'a>(context: &str, expr: &'a Expr) -> Result<(&'a Expr, &'a [Expr])> {
238
    let elems = expr.as_list().ok_or_else(|| {
        Error::Compile(format!(
            "{context}: end clause must be a list, got {expr:?}"
        ))
    })?;
238
    if elems.is_empty() {
        return Err(Error::Compile(format!(
            "{context}: end clause must have a test form"
        )));
238
    }
238
    Ok((&elems[0], &elems[1..]))
238
}
fn do_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
    if args.len() < 2 {
        return Err(Error::Compile(
            "DO requires a variable list and an end clause".to_string(),
        ));
    }
    let vars = parse_do_vars("DO", &args[0])?;
    let (end_test, result_forms) = parse_end_clause("DO", &args[1])?;
    let end_test = end_test.clone();
    let result_forms: Vec<Expr> = result_forms.to_vec();
    let body = &args[2..];
    let init_values: Vec<(String, Expr, Option<Expr>)> = vars
        .into_iter()
        .map(|v| {
            let val = match v.init {
                Some(expr) => eval_value(symbols, &expr)?,
                None => Expr::Nil,
            };
            Ok((v.name, val, v.step))
        })
        .collect::<Result<_>>()?;
    let mut local = symbols.clone();
    let mut stepped: Vec<(String, Option<Expr>)> = Vec::new();
    for (name, val, step) in &init_values {
        local.define(Symbol::new(name, SymbolKind::Variable).with_value(val.clone()));
        stepped.push((name.clone(), step.clone()));
    }
    loop {
        let test = eval_value(&mut local, &end_test)?;
        if is_truthy(&test) {
            return if result_forms.is_empty() {
                Ok(Expr::Nil)
            } else {
                eval_body(&mut local, &result_forms)
            };
        }
        for expr in body {
            eval_value(&mut local, expr)?;
        }
        let new_values: Vec<(&str, Expr)> = stepped
            .iter()
            .filter_map(|(name, step)| {
                step.as_ref()
                    .map(|s| eval_value(&mut local, s).map(|v| (name.as_str(), v)))
            })
            .collect::<Result<_>>()?;
        for (name, val) in new_values {
            local
                .lookup_mut(name)
                .expect("DO variable must exist")
                .set_value(val);
        }
    }
}
fn do_star_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
    if args.len() < 2 {
        return Err(Error::Compile(
            "DO* requires a variable list and an end clause".to_string(),
        ));
    }
    let vars = parse_do_vars("DO*", &args[0])?;
    let (end_test, result_forms) = parse_end_clause("DO*", &args[1])?;
    let end_test = end_test.clone();
    let result_forms: Vec<Expr> = result_forms.to_vec();
    let body = &args[2..];
    let mut local = symbols.clone();
    let mut stepped: Vec<(String, Option<Expr>)> = Vec::new();
    for v in vars {
        let val = match v.init {
            Some(expr) => eval_value(&mut local, &expr)?,
            None => Expr::Nil,
        };
        local.define(Symbol::new(&v.name, SymbolKind::Variable).with_value(val));
        stepped.push((v.name, v.step));
    }
    loop {
        let test = eval_value(&mut local, &end_test)?;
        if is_truthy(&test) {
            return if result_forms.is_empty() {
                Ok(Expr::Nil)
            } else {
                eval_body(&mut local, &result_forms)
            };
        }
        for expr in body {
            eval_value(&mut local, expr)?;
        }
        for (name, step) in &stepped {
            if let Some(s) = step {
                let val = eval_value(&mut local, s)?;
                local
                    .lookup_mut(name)
                    .expect("DO* variable must exist")
                    .set_value(val);
            }
        }
    }
}
170
fn parse_param_list(context: &str, expr: &Expr) -> Result<Vec<String>> {
170
    let params = parse_lambda_params(context, expr)?;
170
    if !params.optional.is_empty()
170
        || params.rest.is_some()
170
        || !params.key.is_empty()
170
        || !params.aux.is_empty()
    {
        return Err(Error::Compile(format!(
            "{context}: lambda list keywords not supported in this context"
        )));
170
    }
170
    Ok(params.required)
170
}
14248
fn parse_lambda_params(context: &str, expr: &Expr) -> Result<LambdaParams> {
14248
    match expr {
14248
        Expr::List(ps) => {
14248
            let mut params = LambdaParams::simple(Vec::new());
14248
            let mut state = ParseState::Required;
15203
            for param in ps {
15203
                if let Some(sym) = param.as_symbol() {
14999
                    if sym.eq_ignore_ascii_case("&optional") {
102
                        if matches!(
102
                            state,
                            ParseState::Optional
                                | ParseState::Rest
                                | ParseState::Key
                                | ParseState::Aux
                        ) {
                            return Err(Error::Compile(format!(
                                "{context}: &optional after {}",
                                state.name()
                            )));
102
                        }
102
                        state = ParseState::Optional;
102
                        continue;
14897
                    }
14897
                    if sym.eq_ignore_ascii_case("&rest") {
136
                        if matches!(state, ParseState::Rest | ParseState::Key | ParseState::Aux) {
                            return Err(Error::Compile(format!(
                                "{context}: &rest after {}",
                                state.name()
                            )));
136
                        }
136
                        state = ParseState::Rest;
136
                        continue;
14761
                    }
14761
                    if sym.eq_ignore_ascii_case("&key") {
136
                        if matches!(state, ParseState::Key | ParseState::Aux) {
                            return Err(Error::Compile(format!(
                                "{context}: &key after {}",
                                state.name()
                            )));
136
                        }
136
                        state = ParseState::Key;
136
                        continue;
14625
                    }
14625
                    if sym.eq_ignore_ascii_case("&aux") {
68
                        if matches!(state, ParseState::Aux) {
                            return Err(Error::Compile(format!("{context}: &aux after aux")));
68
                        }
68
                        state = ParseState::Aux;
68
                        continue;
14557
                    }
204
                }
14761
                match state {
                    ParseState::Required => {
14319
                        let name = param
14319
                            .as_symbol()
14319
                            .ok_or_else(|| {
                                Error::Compile(format!(
                                    "{context}: required parameter must be a symbol, got {param:?}"
                                ))
                            })?
14319
                            .to_string();
14319
                        params.required.push(name);
                    }
                    ParseState::Optional => {
102
                        let (name, default) = parse_optional_param(context, param)?;
102
                        params.optional.push((name, default));
                    }
                    ParseState::Rest => {
136
                        let name = param
136
                            .as_symbol()
136
                            .ok_or_else(|| {
                                Error::Compile(format!(
                                    "{context}: &rest parameter must be a symbol, got {param:?}"
                                ))
                            })?
136
                            .to_string();
136
                        if params.rest.is_some() {
                            return Err(Error::Compile(format!(
                                "{context}: multiple &rest parameters"
                            )));
136
                        }
136
                        params.rest = Some(name);
136
                        state = ParseState::PostRest;
                    }
                    ParseState::PostRest => {
                        return Err(Error::Compile(format!(
                            "{context}: parameters after &rest must use &key or &aux"
                        )));
                    }
                    ParseState::Key => {
136
                        let (name, default) = parse_optional_param(context, param)?;
136
                        params.key.push((name, default));
                    }
                    ParseState::Aux => {
68
                        let (name, default) = parse_optional_param(context, param)?;
68
                        params.aux.push((name, default));
                    }
                }
            }
14248
            Ok(params)
        }
        other => Err(Error::Compile(format!(
            "{context}: expected parameter list, got {other:?}"
        ))),
    }
14248
}
#[derive(Debug, Clone)]
enum ParseState {
    Required,
    Optional,
    Rest,
    PostRest,
    Key,
    Aux,
}
impl ParseState {
    fn name(&self) -> &'static str {
        match self {
            ParseState::Required => "required",
            ParseState::Optional => "&optional",
            ParseState::Rest => "&rest",
            ParseState::PostRest => "post-&rest",
            ParseState::Key => "&key",
            ParseState::Aux => "&aux",
        }
    }
}
306
fn parse_optional_param(context: &str, param: &Expr) -> Result<(String, Option<Expr>)> {
204
    match param {
102
        Expr::Symbol(name) => Ok((name.clone(), None)),
204
        Expr::List(elems) if elems.len() == 2 => {
204
            let name = elems[0]
204
                .as_symbol()
204
                .ok_or_else(|| {
                    Error::Compile(format!(
                        "{context}: parameter name must be a symbol, got {:?}",
                        elems[0]
                    ))
                })?
204
                .to_string();
204
            Ok((name, Some(elems[1].clone())))
        }
        _ => Err(Error::Compile(format!(
            "{context}: optional parameter must be a symbol or (symbol default), got {param:?}"
        ))),
    }
306
}
// Macros
11968
fn defmacro(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
11968
    if args.len() < 3 {
        return Err(Error::Compile(
            "DEFMACRO requires a name, parameter list, and body".to_string(),
        ));
11968
    }
11968
    let name = match &args[0] {
11968
        Expr::Symbol(s) => s.clone(),
        other => {
            return Err(Error::Compile(format!(
                "DEFMACRO: expected symbol name, got {other:?}"
            )));
        }
    };
11968
    let params = parse_lambda_params("DEFMACRO", &args[1])?;
11968
    if !params.aux.is_empty() {
        return Err(Error::Compile(
            "DEFMACRO: &aux is not yet supported".to_string(),
        ));
11968
    }
11968
    let (doc, body_idx) = match args.get(2) {
        Some(Expr::String(s)) if args.len() > 3 => (Some(s.clone()), 3),
11968
        _ => (None, 2),
    };
11968
    if body_idx >= args.len() {
        return Err(Error::Compile("DEFMACRO: missing body".to_string()));
11968
    }
11968
    let body = if args.len() == body_idx + 1 {
11968
        args[body_idx].clone()
    } else {
        let mut forms = Vec::with_capacity(args.len() - body_idx + 1);
        forms.push(Expr::Symbol("BEGIN".to_string()));
        forms.extend_from_slice(&args[body_idx..]);
        Expr::List(forms)
    };
11968
    let lambda = Expr::Lambda(params, Box::new(body));
11968
    let mut sym = Symbol::new(&name, SymbolKind::Macro).with_function(lambda);
11968
    if let Some(d) = doc {
        sym = sym.with_doc(d);
11968
    }
11968
    symbols.define(sym);
11968
    Ok(Expr::Quote(Box::new(Expr::Symbol(name))))
11968
}
204
fn macro_head_name(expr: &Expr) -> Option<&str> {
204
    match expr {
136
        Expr::Symbol(name) => Some(name),
68
        Expr::Quote(inner) => match inner.as_ref() {
68
            Expr::Symbol(name) => Some(name),
            _ => None,
        },
        _ => None,
    }
204
}
204
fn macroexpand_1_impl(symbols: &mut SymbolTable, form: &Expr) -> Result<Expr> {
204
    match form {
204
        Expr::Quote(inner) => match inner.as_ref() {
204
            Expr::List(elems) if !elems.is_empty() => {
204
                if let Some(name) = macro_head_name(&elems[0])
204
                    && let Some(sym) = symbols.lookup(name)
204
                    && sym.kind() == SymbolKind::Macro
136
                    && let Some(Expr::Lambda(params, body)) = sym.function().cloned()
                {
136
                    return super::expr::expand_macro(symbols, &params, &body, &elems[1..]);
68
                }
68
                Ok(form.clone())
            }
            _ => Ok(form.clone()),
        },
        _ => Ok(form.clone()),
    }
204
}
102
fn macroexpand_1(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
102
    if args.len() != 1 {
        return Err(Error::Arity {
            name: "MACROEXPAND-1".to_string(),
            expected: 1,
            actual: args.len(),
        });
102
    }
102
    let form = resolve_arg(symbols, &args[0])?;
102
    macroexpand_1_impl(symbols, &form)
102
}
34
fn macroexpand(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
34
    if args.len() != 1 {
        return Err(Error::Arity {
            name: "MACROEXPAND".to_string(),
            expected: 1,
            actual: args.len(),
        });
34
    }
34
    let mut form = resolve_arg(symbols, &args[0])?;
    loop {
102
        let expanded = macroexpand_1_impl(symbols, &form)?;
102
        if expanded == form {
34
            break;
68
        }
68
        form = expanded;
    }
34
    Ok(form)
34
}
// Labels
struct LabelDef {
    name: String,
    params: Vec<String>,
    body: Expr,
}
170
fn parse_labels_defs(args: &[Expr]) -> Result<(Vec<LabelDef>, &[Expr])> {
170
    if args.len() < 2 {
34
        return Err(Error::Compile(
34
            "LABELS requires a definitions list and at least one body form".to_string(),
34
        ));
136
    }
136
    let defs_list = args[0].as_list().ok_or_else(|| {
        Error::Compile(format!(
            "LABELS: expected definitions list, got {:?}",
            args[0]
        ))
    })?;
136
    let defs = defs_list
136
        .iter()
170
        .map(|def| {
170
            let elems = def.as_list().ok_or_else(|| {
                Error::Compile(format!("LABELS: expected function definition, got {def:?}"))
            })?;
170
            if elems.len() < 3 {
                return Err(Error::Compile(
                    "LABELS: each definition needs a name, params, and body".to_string(),
                ));
170
            }
170
            let name = elems[0]
170
                .as_symbol()
170
                .ok_or_else(|| {
                    Error::Compile(format!(
                        "LABELS: expected function name, got {:?}",
                        elems[0]
                    ))
                })?
170
                .to_string();
170
            let params = parse_param_list("LABELS", &elems[1])?;
170
            let body = if elems.len() == 3 {
170
                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)
            };
170
            Ok(LabelDef { name, params, body })
170
        })
136
        .collect::<Result<Vec<_>>>()?;
136
    Ok((defs, &args[1..]))
170
}
136
fn define_labels(symbols: &mut SymbolTable, defs: Vec<LabelDef>) -> SymbolTable {
136
    let mut local = symbols.clone();
170
    for def in defs {
170
        let lambda = Expr::Lambda(LambdaParams::simple(def.params), Box::new(def.body));
170
        local.define(Symbol::new(&def.name, SymbolKind::Function).with_function(lambda));
170
    }
136
    local
136
}
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)
}
170
fn compile_labels(
170
    ctx: &mut CompileContext,
170
    emit: &mut FunctionEmitter,
170
    symbols: &mut SymbolTable,
170
    args: &[Expr],
170
) -> Result<()> {
170
    let (defs, body) = parse_labels_defs(args)?;
136
    let mut local = define_labels(symbols, defs);
136
    compile_body(ctx, emit, &mut local, body)
170
}
// DOLIST implementation
306
fn dolist_form(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
306
    if args.len() < 2 {
34
        return Err(Error::Compile(
34
            "DOLIST requires a variable specification and at least one body form".to_string(),
34
        ));
272
    }
272
    let var_spec = args[0].as_list().ok_or_else(|| {
34
        Error::Compile(format!(
34
            "DOLIST: expected variable specification list, got {:?}",
34
            args[0]
34
        ))
34
    })?;
238
    if var_spec.len() < 2 || var_spec.len() > 3 {
        return Err(Error::Compile(
            "DOLIST: variable specification must be (var list) or (var list result)".to_string(),
        ));
238
    }
238
    let var_name = var_spec[0].as_symbol().ok_or_else(|| {
34
        Error::Compile(format!(
34
            "DOLIST: variable must be a symbol, got {:?}",
34
            var_spec[0]
34
        ))
34
    })?;
204
    let list_expr = &var_spec[1];
204
    let result_expr = var_spec.get(2).cloned();
204
    let body = &args[1..];
    // Evaluate the list expression
204
    let list_value = eval_value(symbols, list_expr)?;
204
    let elements = match &list_value {
        Expr::List(elems) => elems.clone(),
34
        Expr::Nil => vec![],
136
        Expr::Quote(inner) => match inner.as_ref() {
136
            Expr::List(elems) => elems.clone(),
            Expr::Nil => vec![],
            _ => {
                return Err(Error::Compile(
                    "DOLIST: list expression must evaluate to a list".to_string(),
                ));
            }
        },
        _ => {
34
            return Err(Error::Compile(
34
                "DOLIST: list expression must evaluate to a list".to_string(),
34
            ));
        }
    };
170
    let saved_loop_var = symbols.lookup(var_name).cloned();
340
    for element in elements {
340
        symbols.define(Symbol::new(var_name, SymbolKind::Variable).with_value(element));
476
        for expr in body {
476
            eval_value(symbols, expr)?;
        }
    }
170
    if let Some(saved) = saved_loop_var {
        symbols.define(saved);
170
    } else {
170
        symbols.remove(var_name);
170
    }
    // Return result expression if provided, otherwise nil
170
    if let Some(result) = result_expr {
34
        eval_value(symbols, &result)
    } else {
136
        Ok(Expr::Nil)
    }
306
}
fn compile_dolist(
    ctx: &mut CompileContext,
    emit: &mut FunctionEmitter,
    symbols: &mut SymbolTable,
    args: &[Expr],
) -> Result<()> {
    if args.len() < 2 {
        return Err(Error::Compile(
            "DOLIST requires a variable specification and at least one body form".to_string(),
        ));
    }
    let var_spec = args[0].as_list().ok_or_else(|| {
        Error::Compile(format!(
            "DOLIST: expected variable specification list, got {:?}",
            args[0]
        ))
    })?;
    if var_spec.len() < 2 || var_spec.len() > 3 {
        return Err(Error::Compile(
            "DOLIST: variable specification must be (var list) or (var list result)".to_string(),
        ));
    }
    let var_name = var_spec[0].as_symbol().ok_or_else(|| {
        Error::Compile(format!(
            "DOLIST: variable must be a symbol, got {:?}",
            var_spec[0]
        ))
    })?;
    let list_expr = &var_spec[1];
    let result_expr = var_spec.get(2).cloned();
    let body = &args[1..];
    // Evaluate the list expression
    let list_value = eval_value(symbols, list_expr)?;
    let elements = match &list_value {
        Expr::List(elems) => elems.clone(),
        Expr::Nil => vec![],
        Expr::Quote(inner) => match inner.as_ref() {
            Expr::List(elems) => elems.clone(),
            Expr::Nil => vec![],
            _ => {
                return Err(Error::Compile(
                    "DOLIST: list expression must evaluate to a list".to_string(),
                ));
            }
        },
        _ => {
            return Err(Error::Compile(
                "DOLIST: list expression must evaluate to a list".to_string(),
            ));
        }
    };
    let saved_loop_var = symbols.lookup(var_name).cloned();
    for element in elements {
        symbols.define(Symbol::new(var_name, SymbolKind::Variable).with_value(element));
        for expr in body {
            compile_for_effect(ctx, emit, symbols, expr)?;
        }
    }
    if let Some(saved) = saved_loop_var {
        symbols.define(saved);
    } else {
        symbols.remove(var_name);
    }
    // Compile result expression if provided, otherwise nil
    if let Some(result) = result_expr {
        compile_expr(ctx, emit, symbols, &result)
    } else {
        compile_nil(emit);
        Ok(())
    }
}
// DEFSTRUCT implementation
43569
fn defstruct(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
43569
    if args.is_empty() {
        return Err(Error::Compile(
            "DEFSTRUCT requires a structure name".to_string(),
        ));
43569
    }
43569
    let name = args[0].as_symbol().ok_or_else(|| {
        Error::Compile(format!(
            "DEFSTRUCT: expected structure name, got {:?}",
            args[0]
        ))
    })?;
43569
    let fields: Vec<String> = args[1..]
43569
        .iter()
174956
        .map(|arg| {
174956
            arg.as_symbol()
174956
                .map(std::string::ToString::to_string)
174956
                .ok_or_else(|| {
                    Error::Compile(format!("DEFSTRUCT: expected field name, got {arg:?}"))
                })
174956
        })
43569
        .collect::<Result<_>>()?;
43569
    symbols.define_struct_fields(name.to_string(), fields.clone());
    // Generate constructor function: make-<name>
43569
    let constructor_name = format!("MAKE-{name}");
43569
    let constructor_params = LambdaParams {
43569
        required: Vec::new(),
43569
        optional: Vec::new(),
43569
        rest: None,
174956
        key: fields.iter().map(|field| (field.clone(), None)).collect(),
43569
        aux: Vec::new(),
    };
43569
    let constructor_body = {
        // Build a list to collect field values from keyword arguments
        // The &key parameters will become local variables, so we just reference them directly
43569
        let field_values: Vec<Expr> = fields
43569
            .iter()
174956
            .map(|field| Expr::Symbol(field.clone()))
43569
            .collect();
43569
        Expr::List(vec![
43569
            Expr::Symbol("MAKE-STRUCT-INSTANCE".to_string()),
43569
            Expr::Quote(Box::new(Expr::String(name.to_string()))),
43569
            Expr::Quote(Box::new(Expr::List(
174956
                fields.iter().map(|f| Expr::String(f.clone())).collect(),
            ))),
43569
            Expr::List(
43569
                vec![Expr::Symbol("LIST".to_string())]
43569
                    .into_iter()
43569
                    .chain(field_values)
43569
                    .collect(),
43569
            ),
        ])
    };
43569
    let constructor = Expr::Lambda(constructor_params, Box::new(constructor_body));
43569
    symbols.define(
43569
        Symbol::new(&constructor_name, SymbolKind::Function).with_function(constructor.clone()),
    );
    // Generate accessor functions: <name>-<field>
174956
    for field in &fields {
174956
        let accessor_name = format!("{name}-{field}");
174956
        let accessor_params = LambdaParams::simple(vec!["INSTANCE".to_string()]);
174956
        let accessor_body = Expr::List(vec![
174956
            Expr::Symbol("STRUCT-FIELD".to_string()),
174956
            Expr::Symbol("INSTANCE".to_string()),
174956
            Expr::Quote(Box::new(Expr::String(field.clone()))),
174956
        ]);
174956
        let accessor = Expr::Lambda(accessor_params, Box::new(accessor_body));
174956
        symbols.define(Symbol::new(&accessor_name, SymbolKind::Function).with_function(accessor));
174956

            
174956
        // Generate setf function: (setf <name>-<field>)
174956
        let setf_accessor_name = format!("(SETF {accessor_name})");
174956
        let setf_params =
174956
            LambdaParams::simple(vec!["INSTANCE".to_string(), "NEW-VALUE".to_string()]);
174956
        let setf_body = Expr::List(vec![
174956
            Expr::Symbol("STRUCT-SET-FIELD".to_string()),
174956
            Expr::Symbol("INSTANCE".to_string()),
174956
            Expr::Quote(Box::new(Expr::String(field.clone()))),
174956
            Expr::Symbol("NEW-VALUE".to_string()),
174956
        ]);
174956
        let setf_function = Expr::Lambda(setf_params, Box::new(setf_body));
174956
        symbols.define(
174956
            Symbol::new(&setf_accessor_name, SymbolKind::Function).with_function(setf_function),
174956
        );
174956
    }
    // Generate predicate function: <name>-p
43569
    let predicate_name = format!("{name}-P");
43569
    let predicate_params = LambdaParams::simple(vec!["OBJECT".to_string()]);
43569
    let predicate_body = Expr::List(vec![
43569
        Expr::Symbol("STRUCT-P".to_string()),
43569
        Expr::Symbol("OBJECT".to_string()),
43569
        Expr::Quote(Box::new(Expr::String(name.to_string()))),
43569
    ]);
43569
    let predicate = Expr::Lambda(predicate_params, Box::new(predicate_body));
43569
    symbols.define(Symbol::new(&predicate_name, SymbolKind::Function).with_function(predicate));
43569
    Ok(Expr::Quote(Box::new(Expr::Symbol(name.to_string()))))
43569
}
fn compile_defstruct(
    ctx: &mut CompileContext,
    emit: &mut FunctionEmitter,
    symbols: &mut SymbolTable,
    args: &[Expr],
) -> Result<()> {
    let result = defstruct(symbols, args)?;
    compile_expr(ctx, emit, symbols, &result)
}
// SETF implementation - generalized assignment
68
fn setf(symbols: &mut SymbolTable, args: &[Expr]) -> Result<Expr> {
68
    if !args.len().is_multiple_of(2) {
        return Err(Error::Compile(
            "SETF requires an even number of arguments (place value pairs)".to_string(),
        ));
68
    }
68
    if args.is_empty() {
        return Ok(Expr::Nil);
68
    }
    // Process each place-value pair
68
    let mut last_value = Expr::Nil;
68
    for pair in args.chunks(2) {
68
        let place = &pair[0];
68
        let value = eval_value(symbols, &pair[1])?;
68
        last_value = set_place(symbols, place, value)?;
    }
34
    Ok(last_value)
68
}
68
fn set_place(symbols: &mut SymbolTable, place: &Expr, value: Expr) -> Result<Expr> {
34
    match place {
        // Simple variable assignment
34
        Expr::Symbol(name) => {
34
            if let Some(sym) = symbols.lookup_mut(name) {
34
                sym.set_value(value.clone());
34
            } else {
                // Define new variable
                symbols.define(Symbol::new(name, SymbolKind::Variable).with_value(value.clone()));
            }
34
            Ok(value)
        }
        // Function call - check if it's a struct accessor
34
        Expr::List(exprs) if !exprs.is_empty() => {
34
            if let Expr::Symbol(func_name) = &exprs[0] {
                // Look for setf function for this accessor
34
                let setf_name = format!("(SETF {func_name})");
34
                if symbols.contains(&setf_name) {
                    // Call the setf function with the arguments and the new value
34
                    let mut setf_args = exprs[1..].to_vec();
34
                    setf_args.push(value.clone());
34
                    let call_args: Vec<Expr> = [Expr::Symbol(setf_name)]
34
                        .into_iter()
34
                        .chain(setf_args)
34
                        .collect();
34
                    super::expr::call(symbols, &call_args)
                } else {
                    Err(Error::Compile(format!(
                        "No setf method defined for accessor '{func_name}'"
                    )))
                }
            } else {
                Err(Error::Compile(
                    "Invalid place in SETF - expected function call".to_string(),
                ))
            }
        }
        _ => Err(Error::Compile(format!(
            "Invalid place in SETF: {}",
            format_expr(place)
        ))),
    }
68
}
fn compile_setf(
    ctx: &mut CompileContext,
    emit: &mut FunctionEmitter,
    symbols: &mut SymbolTable,
    args: &[Expr],
) -> Result<()> {
    let result = setf(symbols, args)?;
    compile_expr(ctx, emit, symbols, &result)
}