1
use tracing::debug;
2

            
3
use crate::ast::{Expr, LambdaParams, Program};
4
use crate::error::{Error, Result};
5
use crate::runtime::Value;
6
use crate::runtime::{Symbol, SymbolKind, SymbolTable};
7
use scripting_format::ValueType;
8

            
9
use super::context::CompileContext;
10
use super::emit::FunctionEmitter;
11
use super::layout::{GcLocals, OutputSerializer};
12

            
13
pub const LOCAL_GC_ARR: u32 = 0;
14
pub const LOCAL_IDX: u32 = 1;
15
pub const LOCAL_OUTPUT_BASE: u32 = 2;
16

            
17
12113
pub fn compile_program(
18
12113
    ctx: &mut CompileContext,
19
12113
    emit: &mut FunctionEmitter,
20
12113
    symbols: &mut SymbolTable,
21
12113
    program: &Program,
22
12113
) -> Result<()> {
23
12113
    if program.exprs.is_empty() {
24
1
        compile_nil(emit);
25
1
        return Ok(());
26
12112
    }
27
12112
    for expr in &program.exprs[..program.exprs.len() - 1] {
28
6936
        compile_for_effect(ctx, emit, symbols, expr)?;
29
    }
30
12112
    compile_expr(ctx, emit, symbols, program.exprs.last().unwrap())
31
12113
}
32

            
33
22451
pub(super) fn compile_expr(
34
22451
    ctx: &mut CompileContext,
35
22451
    emit: &mut FunctionEmitter,
36
22451
    symbols: &mut SymbolTable,
37
22451
    expr: &Expr,
38
22451
) -> Result<()> {
39
13534
    match expr {
40
        Expr::Nil => {
41
171
            debug!("compiling nil");
42
171
            compile_nil(emit);
43
171
            Ok(())
44
        }
45
138
        Expr::Bool(b) => {
46
138
            debug!(value = b, "compiling bool");
47
138
            compile_bool(emit, *b);
48
138
            Ok(())
49
        }
50
987
        Expr::Number(n) => {
51
987
            debug!(numer = *n.numer(), denom = *n.denom(), "compiling number");
52
987
            compile_number(emit, *n.numer(), *n.denom());
53
987
            Ok(())
54
        }
55
579
        Expr::String(s) => {
56
579
            debug!(len = s.len(), "compiling string");
57
579
            compile_string(ctx, emit, s);
58
579
            Ok(())
59
        }
60
648
        Expr::Symbol(name) => {
61
648
            debug!(symbol = %name, "resolving symbol");
62
648
            let resolved = resolve_arg(symbols, expr)?;
63
477
            compile_expr(ctx, emit, symbols, &resolved)
64
        }
65
        Expr::Keyword(name) => {
66
            debug!(keyword = %name, "compiling keyword");
67
            compile_symbol(ctx, emit, &format!(":{name}"));
68
            Ok(())
69
        }
70
6258
        Expr::Quote(inner) => {
71
6258
            debug!("compiling quote");
72
6258
            compile_quoted_expr(ctx, emit, inner)
73
        }
74
13534
        Expr::List(elems) if elems.is_empty() => {
75
34
            debug!("compiling empty list as nil");
76
34
            compile_nil(emit);
77
34
            Ok(())
78
        }
79
13500
        Expr::List(elems) => compile_call(ctx, emit, symbols, elems),
80
68
        Expr::Quasiquote(inner) => {
81
68
            let expanded = expand_quasiquote(symbols, inner)?;
82
68
            compile_expr(ctx, emit, symbols, &expanded)
83
        }
84
        Expr::Unquote(_) | Expr::UnquoteSplicing(_) => {
85
34
            Err(Error::Compile("unquote outside of quasiquote".to_string()))
86
        }
87
        Expr::Lambda(_, _) => {
88
            let s = format_expr(expr);
89
            compile_string(ctx, emit, &s);
90
            Ok(())
91
        }
92
        Expr::RuntimeValue(_) => {
93
34
            if let Expr::RuntimeValue(Value::Struct { name, fields }) = expr
94
34
                && name == "TAG"
95
            {
96
34
                let name_val = fields.first().cloned().unwrap_or(Value::Nil);
97
34
                let value_val = fields.get(1).cloned().unwrap_or(Value::Nil);
98
34
                let name_str = match name_val {
99
34
                    Value::String(s) => s,
100
                    Value::Symbol(s) => s,
101
                    Value::Nil => String::new(),
102
                    other => {
103
                        return Err(Error::Compile(format!(
104
                            "TAG name must be string/symbol, got {}",
105
                            other.type_name()
106
                        )));
107
                    }
108
                };
109
34
                let value_str = match value_val {
110
34
                    Value::String(s) => s,
111
                    Value::Symbol(s) => s,
112
                    Value::Nil => String::new(),
113
                    other => {
114
                        return Err(Error::Compile(format!(
115
                            "TAG value must be string/symbol, got {}",
116
                            other.type_name()
117
                        )));
118
                    }
119
                };
120
34
                if name_str.len() > u16::MAX as usize || value_str.len() > u16::MAX as usize {
121
                    return Err(Error::Compile(
122
                        "TAG name/value exceed u16 size limit".to_string(),
123
                    ));
124
34
                }
125
34
                let name_data_idx = ctx.add_data(name_str.as_bytes());
126
34
                let value_data_idx = ctx.add_data(value_str.as_bytes());
127
34
                let gc = GcLocals {
128
34
                    type_idx: ctx.type_idx("i8_array"),
129
34
                    arr: LOCAL_GC_ARR,
130
34
                    idx: LOCAL_IDX,
131
34
                };
132
34
                let mut serializer = OutputSerializer::new(LOCAL_OUTPUT_BASE);
133
34
                serializer.begin_output(emit);
134
34
                serializer.write_tag_gc(
135
34
                    emit,
136
34
                    name_data_idx,
137
34
                    name_str.len() as u32,
138
34
                    value_data_idx,
139
34
                    value_str.len() as u32,
140
34
                    &gc,
141
                );
142
34
                return Ok(());
143
            }
144
            if let Expr::RuntimeValue(val) = expr {
145
                compile_string(ctx, emit, &format_runtime_value(val));
146
                Ok(())
147
            } else {
148
                unreachable!()
149
            }
150
        }
151
        _ => Err(Error::Compile(format!("unsupported expression: {expr:?}"))),
152
    }
153
22451
}
154

            
155
6326
pub(super) fn compile_quoted_expr(
156
6326
    ctx: &mut CompileContext,
157
6326
    emit: &mut FunctionEmitter,
158
6326
    inner: &Expr,
159
6326
) -> Result<()> {
160
6326
    match inner {
161
        Expr::Nil => {
162
            compile_nil(emit);
163
            Ok(())
164
        }
165
        Expr::Bool(b) => {
166
            compile_bool(emit, *b);
167
            Ok(())
168
        }
169
102
        Expr::Number(n) => {
170
102
            compile_number(emit, *n.numer(), *n.denom());
171
102
            Ok(())
172
        }
173
34
        Expr::String(s) => {
174
34
            compile_string(ctx, emit, s);
175
34
            Ok(())
176
        }
177
5884
        Expr::Symbol(s) => {
178
5884
            compile_symbol(ctx, emit, s);
179
5884
            Ok(())
180
        }
181
        Expr::Keyword(s) => {
182
            compile_symbol(ctx, emit, &format!(":{s}"));
183
            Ok(())
184
        }
185
306
        Expr::List(elems) => {
186
306
            let s = format!(
187
                "({})",
188
306
                elems.iter().map(format_expr).collect::<Vec<_>>().join(" ")
189
            );
190
306
            compile_string(ctx, emit, &s);
191
306
            Ok(())
192
        }
193
        Expr::Cons(car, cdr) => {
194
            compile_string(
195
                ctx,
196
                emit,
197
                &format!("({} . {})", format_expr(car), format_expr(cdr)),
198
            );
199
            Ok(())
200
        }
201
        Expr::Quasiquote(e) => {
202
            compile_string(ctx, emit, &format!("`{}", format_expr(e)));
203
            Ok(())
204
        }
205
        Expr::Unquote(e) => {
206
            compile_string(ctx, emit, &format!(",{}", format_expr(e)));
207
            Ok(())
208
        }
209
        Expr::UnquoteSplicing(e) => {
210
            compile_string(ctx, emit, &format!(",@{}", format_expr(e)));
211
            Ok(())
212
        }
213
        Expr::RuntimeValue(_) => Err(Error::Compile(
214
            "runtime values cannot be quoted in WASM".to_string(),
215
        )),
216
        _ => Err(Error::Compile(format!(
217
            "unsupported quoted expression: {inner:?}"
218
        ))),
219
    }
220
6326
}
221

            
222
818
pub(super) fn compile_nil(emit: &mut FunctionEmitter) {
223
818
    let mut serializer = OutputSerializer::new(LOCAL_OUTPUT_BASE);
224
818
    serializer.begin_output(emit);
225
818
    serializer.write_debug_nil(emit);
226
818
}
227

            
228
614
pub(super) fn compile_bool(emit: &mut FunctionEmitter, value: bool) {
229
614
    let mut serializer = OutputSerializer::new(LOCAL_OUTPUT_BASE);
230
614
    serializer.begin_output(emit);
231
614
    serializer.write_debug_bool(emit, value);
232
614
}
233

            
234
2755
pub(super) fn compile_number(emit: &mut FunctionEmitter, numer: i64, denom: i64) {
235
2755
    let mut serializer = OutputSerializer::new(LOCAL_OUTPUT_BASE);
236
2755
    serializer.begin_output(emit);
237
2755
    serializer.write_debug_number(emit, numer, denom);
238
2755
}
239

            
240
6837
fn compile_text(
241
6837
    ctx: &mut CompileContext,
242
6837
    emit: &mut FunctionEmitter,
243
6837
    value_type: ValueType,
244
6837
    s: &str,
245
6837
) {
246
6837
    let data_idx = ctx.add_data(s.as_bytes());
247
6837
    let gc = GcLocals {
248
6837
        type_idx: ctx.type_idx("i8_array"),
249
6837
        arr: LOCAL_GC_ARR,
250
6837
        idx: LOCAL_IDX,
251
6837
    };
252
6837
    let mut serializer = OutputSerializer::new(LOCAL_OUTPUT_BASE);
253
6837
    serializer.begin_output(emit);
254
6837
    serializer.write_debug_string_gc(emit, value_type, data_idx, s.len() as u32, &gc);
255
6837
}
256

            
257
953
pub(super) fn compile_string(ctx: &mut CompileContext, emit: &mut FunctionEmitter, s: &str) {
258
953
    compile_text(ctx, emit, ValueType::String, s);
259
953
}
260

            
261
5884
pub(super) fn compile_symbol(ctx: &mut CompileContext, emit: &mut FunctionEmitter, s: &str) {
262
5884
    compile_text(ctx, emit, ValueType::Symbol, s);
263
5884
}
264

            
265
22168
pub(crate) fn call(symbols: &mut SymbolTable, elems: &[Expr]) -> Result<Expr> {
266
22168
    let (head, args) = elems
267
22168
        .split_first()
268
22168
        .ok_or_else(|| Error::Compile("empty function call".to_string()))?;
269
22168
    match head {
270
20706
        Expr::Symbol(name) => dispatch_symbol(symbols, name, args),
271
1088
        Expr::Quote(inner) => match inner.as_ref() {
272
1088
            Expr::Symbol(name) => dispatch_symbol(symbols, name, args),
273
            _ => Err(Error::Compile(format!("not callable: {head:?}"))),
274
        },
275
136
        Expr::Lambda(params, body) => call_lambda(symbols, params, body, args),
276
238
        Expr::List(inner) => {
277
238
            let resolved = call(symbols, inner)?;
278
238
            match resolved {
279
238
                Expr::Lambda(params, body) => call_lambda(symbols, &params, &body, args),
280
                _ => Err(Error::Compile("not callable".to_string())),
281
            }
282
        }
283
        _ => Err(Error::Compile(format!("not callable: {head:?}"))),
284
    }
285
22168
}
286

            
287
49640
pub(crate) fn eval_value(symbols: &mut SymbolTable, expr: &Expr) -> Result<Expr> {
288
20842
    match expr {
289
20842
        Expr::List(elems) if !elems.is_empty() => call(symbols, elems),
290
28798
        _ => resolve_arg(symbols, expr),
291
    }
292
49640
}
293

            
294
21794
fn dispatch_symbol(symbols: &mut SymbolTable, name: &str, args: &[Expr]) -> Result<Expr> {
295
21794
    let (func, kind) = {
296
21794
        let sym = symbols
297
21794
            .lookup(name)
298
21794
            .ok_or_else(|| Error::UndefinedSymbol(name.to_string()))?;
299
21794
        (sym.function().cloned(), sym.kind())
300
    };
301
21794
    if kind == SymbolKind::Macro
302
544
        && let Some(Expr::Lambda(params, body)) = func
303
    {
304
544
        let expansion = expand_macro(symbols, &params, &body, args)?;
305
544
        let code = match expansion {
306
510
            Expr::Quote(inner) => *inner,
307
34
            other => other,
308
        };
309
544
        return eval_value(symbols, &code);
310
21250
    }
311
1394
    if let Some(Expr::Lambda(params, body)) = func {
312
1394
        return call_lambda(symbols, &params, &body, args);
313
19856
    }
314
19856
    match kind {
315
7344
        SymbolKind::Native | SymbolKind::Operator => super::native::call(symbols, name, args),
316
12512
        SymbolKind::SpecialForm => super::special::call(symbols, name, args),
317
        _ => Err(Error::Compile(format!("symbol '{name}' is not callable"))),
318
    }
319
21794
}
320

            
321
1190
pub(crate) fn expand_macro(
322
1190
    symbols: &mut SymbolTable,
323
1190
    params: &LambdaParams,
324
1190
    body: &Expr,
325
1190
    args: &[Expr],
326
1190
) -> Result<Expr> {
327
1190
    if !params.aux.is_empty() {
328
        return Err(Error::Compile(
329
            "&aux not yet supported in macros".to_string(),
330
        ));
331
1190
    }
332

            
333
1190
    let min_args = params.required.len();
334
1190
    let max_args = if params.rest.is_some() || !params.key.is_empty() {
335
510
        None
336
    } else {
337
680
        Some(min_args + params.optional.len())
338
    };
339
1190
    if args.len() < min_args || max_args.is_some_and(|max| args.len() > max) {
340
34
        return Err(Error::Arity {
341
34
            name: "macro".to_string(),
342
34
            expected: min_args,
343
34
            actual: args.len(),
344
34
        });
345
1156
    }
346

            
347
1156
    let mut local_symbols = symbols.clone();
348
1156
    let mut arg_idx = 0;
349

            
350
1802
    for param in &params.required {
351
1802
        local_symbols
352
1802
            .define(Symbol::new(param, SymbolKind::Variable).with_value(args[arg_idx].clone()));
353
1802
        arg_idx += 1;
354
1802
    }
355

            
356
1156
    for (param, default) in &params.optional {
357
        let value = if arg_idx < args.len() {
358
            let arg = args[arg_idx].clone();
359
            arg_idx += 1;
360
            arg
361
        } else if let Some(default_expr) = default {
362
            default_expr.clone()
363
        } else {
364
            Expr::Nil
365
        };
366
        local_symbols.define(Symbol::new(param, SymbolKind::Variable).with_value(value));
367
    }
368

            
369
1156
    if let Some(rest_param) = &params.rest {
370
476
        let rest = Expr::Quote(Box::new(Expr::List(args[arg_idx..].to_vec())));
371
476
        local_symbols.define(Symbol::new(rest_param, SymbolKind::Variable).with_value(rest));
372
680
    }
373

            
374
    // Bind key parameters in macros
375
1156
    if !params.key.is_empty() {
376
34
        let remaining_args = &args[arg_idx..];
377
34
        for (param, default) in &params.key {
378
34
            let keyword = Expr::Keyword(param.to_uppercase());
379
34
            let mut found_value = None;
380

            
381
            // Look for keyword argument pairs
382
34
            for i in (0..remaining_args.len() - 1).step_by(2) {
383
34
                if remaining_args[i] == keyword {
384
34
                    found_value = Some(remaining_args[i + 1].clone());
385
34
                    break;
386
                }
387
            }
388

            
389
34
            let value = if let Some(val) = found_value {
390
34
                val
391
            } else if let Some(default_expr) = default {
392
                default_expr.clone()
393
            } else {
394
                Expr::Nil
395
            };
396

            
397
34
            local_symbols.define(Symbol::new(param, SymbolKind::Variable).with_value(value));
398
        }
399
1122
    }
400

            
401
1156
    eval_value(&mut local_symbols, body)
402
1190
}
403

            
404
1768
fn call_lambda(
405
1768
    symbols: &mut SymbolTable,
406
1768
    params: &LambdaParams,
407
1768
    body: &Expr,
408
1768
    args: &[Expr],
409
1768
) -> Result<Expr> {
410
1768
    let min_args = params.required.len();
411
    // If we have &key or &rest, we can have unlimited args
412
1768
    let max_args = if params.rest.is_some() || !params.key.is_empty() {
413
306
        None
414
    } else {
415
1462
        Some(min_args + params.optional.len())
416
    };
417

            
418
1768
    if args.len() < min_args {
419
        return Err(Error::Arity {
420
            name: "lambda".to_string(),
421
            expected: min_args,
422
            actual: args.len(),
423
        });
424
1768
    }
425
1768
    if let Some(max) = max_args
426
1462
        && args.len() > max
427
    {
428
        return Err(Error::Arity {
429
            name: "lambda".to_string(),
430
            expected: max,
431
            actual: args.len(),
432
        });
433
1768
    }
434

            
435
1768
    let mut local_symbols = symbols.clone();
436
1768
    let mut arg_idx = 0;
437

            
438
    // Bind required parameters
439
1768
    for param in &params.required {
440
850
        let resolved = eval_value(symbols, &args[arg_idx])?;
441
850
        local_symbols.define(Symbol::new(param, SymbolKind::Variable).with_value(resolved));
442
850
        arg_idx += 1;
443
    }
444

            
445
    // Bind optional parameters
446
1768
    for (param, default) in &params.optional {
447
102
        let value = if arg_idx < args.len() {
448
34
            eval_value(symbols, &args[arg_idx])?
449
68
        } else if let Some(default_expr) = default {
450
34
            eval_value(symbols, default_expr)?
451
        } else {
452
34
            Expr::Nil
453
        };
454
102
        local_symbols.define(Symbol::new(param, SymbolKind::Variable).with_value(value));
455
102
        if arg_idx < args.len() {
456
34
            arg_idx += 1;
457
68
        }
458
    }
459

            
460
    // Bind rest parameter
461
1768
    if let Some(rest_param) = &params.rest {
462
102
        let rest_args: Vec<Expr> = args[arg_idx..]
463
102
            .iter()
464
170
            .map(|arg| eval_value(symbols, arg))
465
102
            .collect::<Result<_>>()?;
466
102
        let rest_list = if rest_args.is_empty() {
467
34
            Expr::Nil
468
        } else {
469
68
            Expr::List(rest_args)
470
        };
471
102
        local_symbols.define(Symbol::new(rest_param, SymbolKind::Variable).with_value(rest_list));
472
1666
    }
473

            
474
    // Bind key parameters
475
1768
    if !params.key.is_empty() {
476
        // Find keyword arguments in the remaining args
477
204
        let remaining_args = &args[arg_idx..];
478
408
        for (param, default) in &params.key {
479
408
            let keyword = Expr::Keyword(param.to_uppercase());
480
408
            let mut found_value = None;
481

            
482
            // Look for keyword argument pairs
483
408
            if remaining_args.len() >= 2 {
484
782
                for i in (0..remaining_args.len() - 1).step_by(2) {
485
782
                    if remaining_args[i] == keyword {
486
374
                        found_value = Some(eval_value(symbols, &remaining_args[i + 1])?);
487
374
                        break;
488
408
                    }
489
                }
490
34
            }
491

            
492
408
            let value = if let Some(val) = found_value {
493
374
                val
494
34
            } else if let Some(default_expr) = default {
495
                eval_value(symbols, default_expr)?
496
            } else {
497
34
                Expr::Nil
498
            };
499

            
500
408
            local_symbols.define(Symbol::new(param, SymbolKind::Variable).with_value(value));
501
        }
502
1564
    }
503

            
504
    // Bind aux parameters (auxiliary variables)
505
1768
    for (param, init) in &params.aux {
506
68
        let value = if let Some(init_expr) = init {
507
68
            eval_value(&mut local_symbols, init_expr)?
508
        } else {
509
            Expr::Nil
510
        };
511
68
        local_symbols.define(Symbol::new(param, SymbolKind::Variable).with_value(value));
512
    }
513

            
514
1768
    eval_value(&mut local_symbols, body)
515
1768
}
516

            
517
1054
pub(super) fn compile_body(
518
1054
    ctx: &mut CompileContext,
519
1054
    emit: &mut FunctionEmitter,
520
1054
    symbols: &mut SymbolTable,
521
1054
    body: &[Expr],
522
1054
) -> Result<()> {
523
1054
    for expr in &body[..body.len() - 1] {
524
272
        compile_for_effect(ctx, emit, symbols, expr)?;
525
    }
526
1054
    compile_expr(ctx, emit, symbols, body.last().unwrap())
527
1054
}
528

            
529
7208
pub(super) fn compile_for_effect(
530
7208
    ctx: &mut CompileContext,
531
7208
    emit: &mut FunctionEmitter,
532
7208
    symbols: &mut SymbolTable,
533
7208
    expr: &Expr,
534
7208
) -> Result<()> {
535
7208
    match expr {
536
7208
        Expr::List(elems) if matches!(elems.first(), Some(Expr::Symbol(s)) if s == "DEBUG") => {
537
102
            super::native::compile_debug_effect(ctx, emit, symbols, &elems[1..])
538
        }
539
        _ => {
540
7106
            let _ = (ctx, emit);
541
7106
            eval_value(symbols, expr)?;
542
7106
            Ok(())
543
        }
544
    }
545
7208
}
546

            
547
13738
pub(super) fn compile_call(
548
13738
    ctx: &mut CompileContext,
549
13738
    emit: &mut FunctionEmitter,
550
13738
    symbols: &mut SymbolTable,
551
13738
    elems: &[Expr],
552
13738
) -> Result<()> {
553
13738
    let (head, args) = elems
554
13738
        .split_first()
555
13738
        .ok_or_else(|| Error::Compile("empty function call".to_string()))?;
556
13738
    match head {
557
13398
        Expr::Symbol(name) => compile_symbol_call(ctx, emit, symbols, name, args),
558
272
        Expr::Quote(inner) => match inner.as_ref() {
559
272
            Expr::Symbol(name) => compile_symbol_call(ctx, emit, symbols, name, args),
560
            _ => Err(Error::Compile(format!("not callable: {head:?}"))),
561
        },
562
        Expr::Lambda(params, body) => compile_lambda_call(ctx, emit, symbols, params, body, args),
563
68
        Expr::List(inner) => {
564
68
            let resolved = call(symbols, inner)?;
565
68
            match resolved {
566
68
                Expr::Lambda(params, body) => {
567
68
                    compile_lambda_call(ctx, emit, symbols, &params, &body, args)
568
                }
569
                _ => Err(Error::Compile("not callable".to_string())),
570
            }
571
        }
572
        _ => Err(Error::Compile(format!("not callable: {head:?}"))),
573
    }
574
13738
}
575

            
576
13670
fn compile_symbol_call(
577
13670
    ctx: &mut CompileContext,
578
13670
    emit: &mut FunctionEmitter,
579
13670
    symbols: &mut SymbolTable,
580
13670
    name: &str,
581
13670
    args: &[Expr],
582
13670
) -> Result<()> {
583
13636
    let (func, kind) = {
584
13670
        let sym = symbols
585
13670
            .lookup(name)
586
13670
            .ok_or_else(|| Error::UndefinedSymbol(name.to_string()))?;
587
13636
        (sym.function().cloned(), sym.kind())
588
    };
589
13636
    if kind == SymbolKind::Macro
590
510
        && let Some(Expr::Lambda(params, body)) = func
591
    {
592
510
        let expansion = expand_macro(symbols, &params, &body, args)?;
593
476
        let code = match expansion {
594
374
            Expr::Quote(inner) => *inner,
595
102
            other => other,
596
        };
597
476
        return compile_expr(ctx, emit, symbols, &code);
598
13126
    }
599
850
    if let Some(Expr::Lambda(params, body)) = func {
600
850
        return compile_lambda_call(ctx, emit, symbols, &params, &body, args);
601
12276
    }
602
12276
    match kind {
603
        SymbolKind::Native | SymbolKind::Operator => {
604
3298
            super::native::compile(ctx, emit, symbols, name, args)
605
        }
606
8978
        SymbolKind::SpecialForm => super::special::compile(ctx, emit, symbols, name, args),
607
        _ => Err(Error::Compile(format!("symbol '{name}' is not callable"))),
608
    }
609
13670
}
610

            
611
918
fn compile_lambda_call(
612
918
    ctx: &mut CompileContext,
613
918
    emit: &mut FunctionEmitter,
614
918
    symbols: &mut SymbolTable,
615
918
    params: &LambdaParams,
616
918
    body: &Expr,
617
918
    args: &[Expr],
618
918
) -> Result<()> {
619
918
    let min_args = params.required.len();
620
918
    let max_args = if params.rest.is_some() || !params.key.is_empty() {
621
34
        None
622
    } else {
623
884
        Some(min_args + params.optional.len())
624
    };
625

            
626
918
    if args.len() < min_args {
627
34
        return Err(Error::Arity {
628
34
            name: "lambda".to_string(),
629
34
            expected: min_args,
630
34
            actual: args.len(),
631
34
        });
632
884
    }
633
884
    if let Some(max) = max_args
634
850
        && args.len() > max
635
    {
636
        return Err(Error::Arity {
637
            name: "lambda".to_string(),
638
            expected: max,
639
            actual: args.len(),
640
        });
641
884
    }
642

            
643
884
    let mut local = symbols.clone();
644
884
    let mut arg_idx = 0;
645

            
646
1326
    for param in &params.required {
647
1326
        let resolved = eval_value(symbols, &args[arg_idx])?;
648
1326
        local.define(Symbol::new(param, SymbolKind::Variable).with_value(resolved));
649
1326
        arg_idx += 1;
650
    }
651

            
652
884
    for (param, default) in &params.optional {
653
        let value = if arg_idx < args.len() {
654
            eval_value(symbols, &args[arg_idx])?
655
        } else if let Some(default_expr) = default {
656
            eval_value(symbols, default_expr)?
657
        } else {
658
            Expr::Nil
659
        };
660
        local.define(Symbol::new(param, SymbolKind::Variable).with_value(value));
661
        if arg_idx < args.len() {
662
            arg_idx += 1;
663
        }
664
    }
665

            
666
884
    if let Some(rest_param) = &params.rest {
667
        let rest_args: Vec<Expr> = args[arg_idx..]
668
            .iter()
669
            .map(|arg| eval_value(symbols, arg))
670
            .collect::<Result<_>>()?;
671
        let rest_list = if rest_args.is_empty() {
672
            Expr::Nil
673
        } else {
674
            Expr::List(rest_args)
675
        };
676
        local.define(Symbol::new(rest_param, SymbolKind::Variable).with_value(rest_list));
677
884
    }
678

            
679
    // Bind key parameters
680
884
    if !params.key.is_empty() {
681
        // Find keyword arguments in the remaining args
682
34
        let remaining_args = &args[arg_idx..];
683
68
        for (param, default) in &params.key {
684
68
            let keyword = Expr::Keyword(param.to_uppercase());
685
68
            let mut found_value = None;
686

            
687
            // Look for keyword argument pairs
688
68
            if remaining_args.len() >= 2 {
689
102
                for i in (0..remaining_args.len() - 1).step_by(2) {
690
102
                    if remaining_args[i] == keyword {
691
68
                        found_value = Some(eval_value(symbols, &remaining_args[i + 1])?);
692
68
                        break;
693
34
                    }
694
                }
695
            }
696

            
697
68
            let value = if let Some(val) = found_value {
698
68
                val
699
            } else if let Some(default_expr) = default {
700
                eval_value(symbols, default_expr)?
701
            } else {
702
                Expr::Nil
703
            };
704

            
705
68
            local.define(Symbol::new(param, SymbolKind::Variable).with_value(value));
706
        }
707
850
    }
708

            
709
884
    for (param, init) in &params.aux {
710
        let value = if let Some(init_expr) = init {
711
            eval_value(&mut local, init_expr)?
712
        } else {
713
            Expr::Nil
714
        };
715
        local.define(Symbol::new(param, SymbolKind::Variable).with_value(value));
716
    }
717
884
    compile_expr(ctx, emit, &mut local, body)
718
918
}
719

            
720
442
fn expand_quasiquote(symbols: &mut SymbolTable, expr: &Expr) -> Result<Expr> {
721
306
    fn splice_elements(resolved: Expr) -> Result<Vec<Expr>> {
722
306
        match resolved {
723
            Expr::Nil => Ok(Vec::new()),
724
            Expr::List(elems) => Ok(elems),
725
306
            Expr::Quote(inner) => match *inner {
726
                Expr::Nil => Ok(Vec::new()),
727
306
                Expr::List(elems) => Ok(elems),
728
                other => Err(Error::Compile(format!(
729
                    "unquote-splicing requires a list, got {}",
730
                    format_expr(&other)
731
                ))),
732
            },
733
            other => Err(Error::Compile(format!(
734
                "unquote-splicing requires a list, got {}",
735
                format_expr(&other)
736
            ))),
737
        }
738
306
    }
739

            
740
2074
    fn quasiquote_data(symbols: &mut SymbolTable, expr: &Expr) -> Result<Expr> {
741
2074
        match expr {
742
408
            Expr::Unquote(inner) => resolve_arg(symbols, inner),
743
            Expr::UnquoteSplicing(_) => Err(Error::Compile(
744
                "unquote-splicing outside of list in quasiquote".to_string(),
745
            )),
746
646
            Expr::List(elems) => {
747
646
                let mut resolved: Vec<Expr> = Vec::new();
748
1938
                for elem in elems {
749
1938
                    match elem {
750
306
                        Expr::UnquoteSplicing(inner) => {
751
306
                            let spliced = resolve_arg(symbols, inner)?;
752
306
                            resolved.extend(splice_elements(spliced)?);
753
                        }
754
1632
                        _ => resolved.push(quasiquote_data(symbols, elem)?),
755
                    }
756
                }
757
646
                Ok(Expr::List(resolved))
758
            }
759
            Expr::Cons(car, cdr) => {
760
                let car = quasiquote_data(symbols, car)?;
761
                let cdr = quasiquote_data(symbols, cdr)?;
762
                Ok(Expr::cons(car, cdr))
763
            }
764
1020
            _ => Ok(expr.clone()),
765
        }
766
2074
    }
767

            
768
442
    Ok(Expr::Quote(Box::new(quasiquote_data(symbols, expr)?)))
769
442
}
770

            
771
39579
pub(crate) fn resolve_arg(symbols: &mut SymbolTable, expr: &Expr) -> Result<Expr> {
772
39579
    match expr {
773
        Expr::Nil
774
        | Expr::Bool(_)
775
        | Expr::Number(_)
776
        | Expr::String(_)
777
        | Expr::Quote(_)
778
        | Expr::Keyword(_)
779
29343
        | Expr::RuntimeValue(_) => Ok(expr.clone()),
780
        Expr::Lambda(_, _) => Ok(expr.clone()),
781
544
        Expr::Cons(_, _) | Expr::List(_) => Ok(expr.clone()),
782
374
        Expr::Quasiquote(inner) => expand_quasiquote(symbols, inner),
783
        Expr::Unquote(_) | Expr::UnquoteSplicing(_) => {
784
            Err(Error::Compile("unquote outside of quasiquote".to_string()))
785
        }
786
9318
        Expr::Symbol(name) => {
787
9249
            let (value, kind, has_fn) = {
788
9318
                let sym = symbols
789
9318
                    .lookup(name)
790
9318
                    .ok_or_else(|| Error::UndefinedSymbol(name.clone()))?;
791
9249
                (sym.value().cloned(), sym.kind(), sym.function().is_some())
792
            };
793
9249
            if let Some(value) = value {
794
9113
                return resolve_arg(symbols, &value);
795
136
            }
796
            match kind {
797
68
                SymbolKind::Native | SymbolKind::Operator => Err(Error::Compile(format!(
798
68
                    "'{name}' is a function and cannot be used as a value"
799
68
                ))),
800
34
                SymbolKind::SpecialForm => Err(Error::Compile(format!(
801
34
                    "'{name}' is a special form and cannot be used as a value"
802
34
                ))),
803
34
                SymbolKind::Macro => Err(Error::Compile(format!(
804
34
                    "'{name}' is a macro and cannot be used as a value"
805
34
                ))),
806
                _ if has_fn => Err(Error::Compile(format!(
807
                    "'{name}' is a function; use #' or FUNCTION to access"
808
                ))),
809
                _ => Err(Error::Compile(format!("symbol '{name}' has no value"))),
810
            }
811
        }
812
    }
813
39579
}
814

            
815
3502
pub(crate) fn format_expr(expr: &Expr) -> String {
816
1836
    match expr {
817
        Expr::Nil => "NIL".to_string(),
818
102
        Expr::Bool(true) => "#T".to_string(),
819
        Expr::Bool(false) => "NIL".to_string(),
820
1836
        Expr::Number(n) if *n.denom() == 1 => n.numer().to_string(),
821
        Expr::Number(n) => format!("{}/{}", n.numer(), n.denom()),
822
408
        Expr::String(s) => s.clone(),
823
510
        Expr::Symbol(s) => s.clone(),
824
        Expr::Keyword(s) => format!(":{s}"),
825
        Expr::Cons(car, cdr) => format!("({} . {})", format_expr(car), format_expr(cdr)),
826
204
        Expr::List(elems) => {
827
204
            let inner: Vec<_> = elems.iter().map(format_expr).collect();
828
204
            format!("({})", inner.join(" "))
829
        }
830
204
        Expr::Quote(e) => format!("'{}", format_expr(e)),
831
        Expr::Quasiquote(e) => format!("`{}", format_expr(e)),
832
        Expr::Unquote(e) => format!(",{}", format_expr(e)),
833
        Expr::UnquoteSplicing(e) => format!(",@{}", format_expr(e)),
834
102
        Expr::Lambda(params, body) => {
835
102
            format!(
836
                "(LAMBDA ({}) {})",
837
102
                format_lambda_params(params),
838
102
                format_expr(body)
839
            )
840
        }
841
136
        Expr::RuntimeValue(val) => format_runtime_value(val),
842
    }
843
3502
}
844

            
845
782
fn format_runtime_value(val: &Value) -> String {
846
272
    match val {
847
68
        Value::Nil => "NIL".to_string(),
848
        Value::Bool(true) => "#T".to_string(),
849
34
        Value::Bool(false) => "NIL".to_string(),
850
272
        Value::Number(n) if *n.denom() == 1 => n.numer().to_string(),
851
        Value::Number(n) => format!("{}/{}", n.numer(), n.denom()),
852
272
        Value::String(s) => format!("\"{s}\""),
853
        Value::Symbol(s) => s.clone(),
854
        Value::Pair(_) | Value::Vector(_) | Value::Closure(_) => {
855
            format!("#<{}>", val.type_name())
856
        }
857
136
        Value::Struct { name, fields } => {
858
136
            let field_strs: Vec<_> = fields.iter().map(format_runtime_value).collect();
859
136
            format!("#S({name} {})", field_strs.join(" "))
860
        }
861
    }
862
782
}
863

            
864
102
fn format_lambda_params(params: &LambdaParams) -> String {
865
102
    let mut parts = Vec::new();
866

            
867
    // Required parameters
868
102
    parts.extend(params.required.iter().cloned());
869

            
870
    // Optional parameters
871
102
    if !params.optional.is_empty() {
872
        parts.push("&optional".to_string());
873
        for (name, default) in &params.optional {
874
            if let Some(default_expr) = default {
875
                parts.push(format!("({} {})", name, format_expr(default_expr)));
876
            } else {
877
                parts.push(name.clone());
878
            }
879
        }
880
102
    }
881

            
882
    // Rest parameter
883
102
    if let Some(rest) = &params.rest {
884
        parts.push("&rest".to_string());
885
        parts.push(rest.clone());
886
102
    }
887

            
888
    // Key parameters
889
102
    if !params.key.is_empty() {
890
        parts.push("&key".to_string());
891
        for (name, default) in &params.key {
892
            if let Some(default_expr) = default {
893
                parts.push(format!("({} {})", name, format_expr(default_expr)));
894
            } else {
895
                parts.push(name.clone());
896
            }
897
        }
898
102
    }
899

            
900
    // Aux parameters
901
102
    if !params.aux.is_empty() {
902
        parts.push("&aux".to_string());
903
        for (name, init) in &params.aux {
904
            if let Some(init_expr) = init {
905
                parts.push(format!("({} {})", name, format_expr(init_expr)));
906
            } else {
907
                parts.push(name.clone());
908
            }
909
        }
910
102
    }
911

            
912
102
    parts.join(" ")
913
102
}